/// <summary> /// Gets occurrence data for the selected group /// </summary> /// <param name="group">The group.</param> /// <param name="fromDateTime">From date time.</param> /// <param name="toDateTime">To date time.</param> /// <param name="locationIds">The location ids.</param> /// <param name="scheduleIds">The schedule ids.</param> /// <returns></returns> public List <AttendanceOccurrence> GetGroupOccurrences(Group group, DateTime?fromDateTime, DateTime?toDateTime, List <int> locationIds, List <int> scheduleIds) { var qry = Queryable().Where(a => a.GroupId == group.Id); // Filter by date range if (fromDateTime.HasValue) { var fromDate = fromDateTime.Value.Date; qry = qry.Where(a => DbFunctions.TruncateTime(a.OccurrenceDate) >= (fromDate)); } if (toDateTime.HasValue) { var toDate = toDateTime.Value.Date; qry = qry.Where(a => DbFunctions.TruncateTime(a.OccurrenceDate) < (toDate)); } // Location Filter if (locationIds.Any()) { qry = qry.Where(a => locationIds.Contains(a.LocationId ?? 0)); } // Schedule Filter if (scheduleIds.Any()) { qry = qry.Where(a => scheduleIds.Contains(a.ScheduleId ?? 0)); } var occurrences = qry.ToList(); // Create any missing occurrences from the group's schedule (not location schedules) Schedule groupSchedule = null; if (group.ScheduleId.HasValue) { groupSchedule = group.Schedule ?? new ScheduleService((RockContext)Context).Get(group.ScheduleId.Value); } if (groupSchedule == null) { return(occurrences); } var newOccurrences = new List <AttendanceOccurrence>(); var existingDates = occurrences .Where(o => o.ScheduleId.Equals(groupSchedule.Id)) .Select(o => o.OccurrenceDate.Date) .Distinct() .ToList(); var startDate = fromDateTime ?? RockDateTime.Today.AddMonths(-2); var endDate = toDateTime ?? RockDateTime.Today.AddDays(1); if (!string.IsNullOrWhiteSpace(groupSchedule.iCalendarContent)) { // If schedule has an iCal schedule, get all the past occurrences foreach (var occurrence in groupSchedule.GetOccurrences(startDate, endDate)) { var newOccurrence = new AttendanceOccurrence { OccurrenceDate = occurrence.Period.StartTime.Date.Add(occurrence.Period.StartTime.TimeOfDay), GroupId = @group.Id, ScheduleId = groupSchedule.Id }; if (existingDates.Contains(newOccurrence.OccurrenceDate.Date)) { continue; } newOccurrences.Add(newOccurrence); existingDates.Add(newOccurrence.OccurrenceDate.Date); } } else { // if schedule does not have an iCal, then check for weekly schedule and calculate occurrences starting with first attendance or current week if (groupSchedule.WeeklyDayOfWeek.HasValue) { // default to start with date 2 months earlier startDate = fromDateTime ?? RockDateTime.Today.AddMonths(-2); if (existingDates.Any(d => d < startDate)) { startDate = existingDates.Min(); } // Back up start time to the correct day of week while (startDate.DayOfWeek != groupSchedule.WeeklyDayOfWeek.Value) { startDate = startDate.AddDays(-1); } // Add the start time if (groupSchedule.WeeklyTimeOfDay.HasValue) { startDate = startDate.Add(groupSchedule.WeeklyTimeOfDay.Value); } // Create occurrences up to current time while (startDate < endDate) { if (!existingDates.Contains(startDate.Date)) { var newOccurrence = new AttendanceOccurrence { OccurrenceDate = startDate, GroupId = @group.Id, ScheduleId = groupSchedule.Id }; newOccurrences.Add(newOccurrence); } startDate = startDate.AddDays(7); } } } if (newOccurrences.Any()) { // Filter Exclusions var groupType = GroupTypeCache.Get(group.GroupTypeId); foreach (var exclusion in groupType.GroupScheduleExclusions) { if (!exclusion.Start.HasValue || !exclusion.End.HasValue) { continue; } foreach (var occurrence in newOccurrences.ToList()) { if (occurrence.OccurrenceDate.Date >= exclusion.Start.Value && occurrence.OccurrenceDate.Date < exclusion.End.Value.AddDays(1)) { newOccurrences.Remove(occurrence); } } } } foreach (var occurrence in newOccurrences) { occurrences.Add(occurrence); } return(occurrences); }
/// <summary> /// Gets future occurrence data for the selected group (including all scheduled dates). /// </summary> /// <param name="group">The group.</param> /// <param name="toDateTime">To date time. If not supplied, this will default to 6 months from the current date.</param> /// <param name="locationIds">The location ids.</param> /// <param name="scheduleIds">The schedule ids.</param> /// <returns></returns> public List <AttendanceOccurrence> GetFutureGroupOccurrences(Group group, DateTime?toDateTime, string locationIds = null, string scheduleIds = null) { var locationIdList = new List <int>(); if (!string.IsNullOrWhiteSpace(locationIds)) { locationIdList = locationIds.Split(',').Select(int.Parse).ToList(); } var scheduleIdList = new List <int>(); if (!string.IsNullOrWhiteSpace(scheduleIds)) { scheduleIdList = scheduleIds.Split(',').Select(int.Parse).ToList(); } var qry = Queryable("Group,Schedule").AsNoTracking().Where(a => a.GroupId == group.Id); // Filter by date range var fromDate = DateTime.Now.Date; var toDate = fromDate.AddMonths(6); // Default to 6 months in the future. if (toDateTime.HasValue) { toDate = toDateTime.Value.Date; } qry = qry .Where(a => a.OccurrenceDate >= (fromDate)) .Where(a => a.OccurrenceDate < (toDate)); // Location Filter if (locationIdList.Any()) { qry = qry.Where(a => locationIdList.Contains(a.LocationId ?? 0)); } // Schedule Filter if (scheduleIdList.Any()) { qry = qry.Where(a => scheduleIdList.Contains(a.ScheduleId ?? 0)); } var occurrences = qry.ToList(); // Create any missing occurrences from the group's schedule (not location schedules) Schedule groupSchedule = null; if (group.ScheduleId.HasValue) { groupSchedule = group.Schedule ?? new ScheduleService(( RockContext )Context).Get(group.ScheduleId.Value); } if (groupSchedule == null) { return(occurrences); } var newOccurrences = new List <AttendanceOccurrence>(); var existingDates = occurrences .Where(o => o.ScheduleId.Equals(groupSchedule.Id)) .Select(o => o.OccurrenceDate.Date) .Distinct() .ToList(); if (!string.IsNullOrWhiteSpace(groupSchedule.iCalendarContent)) { // If schedule has an iCal schedule, get all the past occurrences foreach (var occurrence in groupSchedule.GetOccurrences(fromDate, toDate)) { var newOccurrence = new AttendanceOccurrence { OccurrenceDate = occurrence.Period.StartTime.Date, GroupId = group.Id, Group = group, ScheduleId = groupSchedule.Id, Schedule = groupSchedule }; if (existingDates.Contains(newOccurrence.OccurrenceDate.Date)) { continue; } newOccurrences.Add(newOccurrence); existingDates.Add(newOccurrence.OccurrenceDate.Date); } } else { // if schedule does not have an iCal, then check for weekly schedule and calculate occurrences starting with first attendance or current week if (groupSchedule.WeeklyDayOfWeek.HasValue) { var startDate = fromDate; // Move start time forward to the correct day of week. while (startDate.DayOfWeek != groupSchedule.WeeklyDayOfWeek.Value) { startDate = startDate.AddDays(1); } // Add the start time if (groupSchedule.WeeklyTimeOfDay.HasValue) { startDate = startDate.Add(groupSchedule.WeeklyTimeOfDay.Value); } // Create occurrences up to current time while (startDate < toDate) { if (!existingDates.Contains(startDate.Date)) { var newOccurrence = new AttendanceOccurrence { OccurrenceDate = startDate, GroupId = group.Id, Group = group, ScheduleId = groupSchedule.Id, Schedule = groupSchedule }; newOccurrences.Add(newOccurrence); } startDate = startDate.AddDays(7); } } } if (newOccurrences.Any()) { // Filter Exclusions var groupType = GroupTypeCache.Get(group.GroupTypeId); foreach (var exclusion in groupType.GroupScheduleExclusions) { if (!exclusion.Start.HasValue || !exclusion.End.HasValue) { continue; } foreach (var occurrence in newOccurrences.ToList()) { if (occurrence.OccurrenceDate >= exclusion.Start.Value.Date && occurrence.OccurrenceDate < exclusion.End.Value.Date.AddDays(1)) { newOccurrences.Remove(occurrence); } } } } foreach (var occurrence in newOccurrences) { occurrences.Add(occurrence); } occurrences = occurrences.OrderBy(o => o.OccurrenceDate).ToList(); return(occurrences); }