/// <summary> /// Copies the properties from another AttendanceOccurrence object to this AttendanceOccurrence object /// </summary> /// <param name="target">The target.</param> /// <param name="source">The source.</param> public static void CopyPropertiesFrom(this AttendanceOccurrence target, AttendanceOccurrence source) { target.Id = source.Id; target.AcceptConfirmationMessage = source.AcceptConfirmationMessage; target.AnonymousAttendanceCount = source.AnonymousAttendanceCount; target.DeclineConfirmationMessage = source.DeclineConfirmationMessage; target.DeclineReasonValueIds = source.DeclineReasonValueIds; target.DidNotOccur = source.DidNotOccur; target.ForeignGuid = source.ForeignGuid; target.ForeignKey = source.ForeignKey; target.GroupId = source.GroupId; target.LocationId = source.LocationId; target.Name = source.Name; target.Notes = source.Notes; target.OccurrenceDate = source.OccurrenceDate; target.OccurrenceSourceDate = source.OccurrenceSourceDate; target.ScheduleId = source.ScheduleId; target.ShowDeclineReasons = source.ShowDeclineReasons; target.StepTypeId = source.StepTypeId; target.SundayDate = source.SundayDate; target.CreatedDateTime = source.CreatedDateTime; target.ModifiedDateTime = source.ModifiedDateTime; target.CreatedByPersonAliasId = source.CreatedByPersonAliasId; target.ModifiedByPersonAliasId = source.ModifiedByPersonAliasId; target.Guid = source.Guid; target.ForeignId = source.ForeignId; }
/// <summary> /// Gets the specified occurrence record, creating it if necessary. Ensures that an AttendanceOccurrence /// record exists for the specified date, schedule, locationId and group. If it doesn't exist, it is /// created and saved to the database. /// NOTE: When looking for a matching occurrence, if null groupId, locationId or scheduleId is given /// any matching record must also not have a group, location or schedule. /// </summary> /// <param name="occurrenceDate">The occurrence date.</param> /// <param name="groupId">The group identifier.</param> /// <param name="locationId">The location identifier.</param> /// <param name="scheduleId">The schedule identifier.</param> /// <param name="includes">Allows including attendance occurrence virtual properties like Attendees.</param> /// <param name="attendanceTypeValueId">The attendance type identifier.</param> /// <returns> /// An existing or new attendance occurrence /// </returns> public AttendanceOccurrence GetOrAdd(DateTime occurrenceDate, int?groupId, int?locationId, int?scheduleId, string includes, int?attendanceTypeValueId) { var occurrence = Get(occurrenceDate, groupId, locationId, scheduleId, includes); if (occurrence == null) { // If occurrence does not yet exist, create it // A new context is used so the occurrence can be saved and used on multiple new attendance records that will be saved at once. using (var newContext = new RockContext()) { occurrence = new AttendanceOccurrence { OccurrenceDate = occurrenceDate, GroupId = groupId, LocationId = locationId, ScheduleId = scheduleId, AttendanceTypeValueId = attendanceTypeValueId }; var newOccurrenceService = new AttendanceOccurrenceService(newContext); newOccurrenceService.Add(occurrence); newContext.SaveChanges(); // Query for the new occurrence using original context. occurrence = Get(occurrence.Id); } } return(occurrence); }
/// <summary> /// Clones this AttendanceOccurrence object to a new AttendanceOccurrence object /// </summary> /// <param name="source">The source.</param> /// <param name="deepCopy">if set to <c>true</c> a deep copy is made. If false, only the basic entity properties are copied.</param> /// <returns></returns> public static AttendanceOccurrence Clone(this AttendanceOccurrence source, bool deepCopy) { if (deepCopy) { return(source.Clone() as AttendanceOccurrence); } else { var target = new AttendanceOccurrence(); target.CopyPropertiesFrom(source); return(target); } }
public AttendanceOccurrence GetOrCreateAttendanceOccurrence(DateTime occurrenceDate, int scheduleId, int?locationId, int groupId) { // There is a unique constraint on OccurrenceDate, ScheduleId, LocationId and GroupId. So there is at most one record. var attendanceOccurrenceQuery = this.Queryable().Where(a => a.OccurrenceDate == occurrenceDate.Date && a.ScheduleId.HasValue && a.ScheduleId == scheduleId && a.GroupId.HasValue && a.GroupId == groupId); if (locationId.HasValue) { attendanceOccurrenceQuery = attendanceOccurrenceQuery.Where(a => a.LocationId.HasValue && a.LocationId.Value == locationId.Value); } else { attendanceOccurrenceQuery = attendanceOccurrenceQuery.Where(a => a.LocationId.HasValue == false); } var attendanceOccurrence = attendanceOccurrenceQuery.FirstOrDefault(); if (attendanceOccurrence != null) { return(attendanceOccurrence); } else { // if the attendance occurrence is not found, create and save it using a separate context, then get it with this context using the created attendanceOccurrence.Id int attendanceOccurrenceId; using (var rockContext = new RockContext()) { var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); if (attendanceOccurrence == null) { attendanceOccurrence = new AttendanceOccurrence { GroupId = groupId, LocationId = locationId, ScheduleId = scheduleId, OccurrenceDate = occurrenceDate }; attendanceOccurrenceService.Add(attendanceOccurrence); rockContext.SaveChanges(); } attendanceOccurrenceId = attendanceOccurrence.Id; } return(this.Get(attendanceOccurrence.Id)); } }
/// <summary> /// Copies the properties from another AttendanceOccurrence object to this AttendanceOccurrence object /// </summary> /// <param name="target">The target.</param> /// <param name="source">The source.</param> public static void CopyPropertiesFrom(this AttendanceOccurrence target, AttendanceOccurrence source) { target.Id = source.Id; target.AnonymousAttendanceCount = source.AnonymousAttendanceCount; target.DidNotOccur = source.DidNotOccur; target.ForeignGuid = source.ForeignGuid; target.ForeignKey = source.ForeignKey; target.GroupId = source.GroupId; target.LocationId = source.LocationId; target.Notes = source.Notes; target.OccurrenceDate = source.OccurrenceDate; target.ScheduleId = source.ScheduleId; target.CreatedDateTime = source.CreatedDateTime; target.ModifiedDateTime = source.ModifiedDateTime; target.CreatedByPersonAliasId = source.CreatedByPersonAliasId; target.ModifiedByPersonAliasId = source.ModifiedByPersonAliasId; target.Guid = source.Guid; target.ForeignId = source.ForeignId; }
private void ProcessObsoleteOccurrenceFields(DbEntityEntry entry) { if (entry.State == EntityState.Modified || entry.State == EntityState.Added) { // NOTE: If they only changed StartDateTime, don't change the Occurrence record. We want to support letting StartDateTime be a different Date than the OccurrenceDate in that situation if (_updatedObsoleteGroupId || _updatedObsoleteLocationId || _updatedObsoleteScheduleId || _updatedObsoleteDidNotOccur) { if (_updatedObsoleteGroupId || _updatedObsoleteLocationId || _updatedObsoleteScheduleId) { // if they changed or set stuff related to AttendanceOccurrence (not including DidNotOccur or StartDateTime) thru obsolete properties, find or create a Matching AttendanceOccurrence Record using (var attendanceOccurrenceRockContext = new RockContext()) { var attendanceOccurrenceService = new AttendanceOccurrenceService(attendanceOccurrenceRockContext); // if GroupId,LocationId, or ScheduleId changed, use StartDateTime's Date as the OccurrenceDate to look up AttendanceOccurrence since it is really a completely different Occurrence if Group,Location or Schedule changes var occurrenceDate = this.StartDateTime.Date; var attendanceOccurrence = attendanceOccurrenceService.Queryable().Where(a => a.GroupId == this.GroupId && a.LocationId == this.LocationId && a.ScheduleId == this.ScheduleId && a.OccurrenceDate == occurrenceDate).FirstOrDefault(); if (attendanceOccurrence != null) { // found a matching attendanceOccurrence, so use that if (_updatedObsoleteDidNotOccur && attendanceOccurrence.DidNotOccur != this.DidNotOccur) { // If DidNotOccur also changed, update the DidNotOccur for the attendanceOccurrence // NOTE: This will update *all* Attendances' DidNotOccur for this AttendanceOccurrence. That is OK. That is what we want to happen. attendanceOccurrence.DidNotOccur = this.DidNotOccur; attendanceOccurrenceRockContext.SaveChanges(); } if (attendanceOccurrence.Id != this.OccurrenceId) { this.OccurrenceId = attendanceOccurrence.Id; } } else { // didn't find a matching attendanceOccurrence, so create and insert a new one attendanceOccurrence = new AttendanceOccurrence { GroupId = this.GroupId, LocationId = this.LocationId, ScheduleId = this.ScheduleId, DidNotOccur = this.DidNotOccur, OccurrenceDate = occurrenceDate }; attendanceOccurrenceService.Add(attendanceOccurrence); attendanceOccurrenceRockContext.SaveChanges(); this.OccurrenceId = attendanceOccurrence.Id; } } } else if (_updatedObsoleteDidNotOccur) { // if they only changed DidNotOccur, but not any of the other obsolete attendanceoccurrence properties, just change the DidNotOccur on the existing AttendanceOccurrence record if (this.Occurrence != null) { this.Occurrence.DidNotOccur = _updatedObsoleteDidNotOccurValue; } } } } }
/// <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 = RockDateTime.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.GetICalOccurrences(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); }
/// <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 => a.OccurrenceDate >= (fromDate)); } if (toDateTime.HasValue) { var toDate = toDateTime.Value.Date; qry = qry.Where(a => 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.GetICalOccurrences(startDate, endDate)) { 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) { // default to start with date 2 months earlier startDate = fromDateTime ?? RockDateTime.Today.AddMonths(-2); if (existingDates.Any(d => d < startDate)) { startDate = existingDates.Min(); } // Roll forward to the first start time that matches the day of the 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, 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); } return(occurrences); }
/// <summary> /// Adds or updates an attendance record and will create the occurrence if needed /// </summary> /// <param name="personAliasId">The person alias identifier.</param> /// <param name="checkinDateTime">The checkin date time.</param> /// <param name="groupId">The group identifier.</param> /// <param name="locationId">The location identifier.</param> /// <param name="scheduleId">The schedule identifier.</param> /// <param name="campusId">The campus identifier.</param> /// <param name="deviceId">The device identifier.</param> /// <param name="searchTypeValueId">The search type value identifier.</param> /// <param name="searchValue">The search value.</param> /// <param name="searchResultGroupId">The search result group identifier.</param> /// <param name="attendanceCodeId">The attendance code identifier.</param> /// <param name="checkedInByPersonAliasId">The checked in by person alias identifier.</param> /// <returns></returns> public Attendance AddOrUpdate(int?personAliasId, DateTime checkinDateTime, int?groupId, int?locationId, int?scheduleId, int?campusId, int?deviceId, int?searchTypeValueId, string searchValue, int?searchResultGroupId, int?attendanceCodeId, int?checkedInByPersonAliasId) { // Check to see if an occurrence exists already var occurrenceService = new AttendanceOccurrenceService((RockContext)Context); var occurrence = occurrenceService.Get(checkinDateTime.Date, groupId, locationId, scheduleId); if (occurrence == null) { // If occurrence does not yet exists, use a new context and create it using (var newContext = new RockContext()) { occurrence = new AttendanceOccurrence { OccurrenceDate = checkinDateTime.Date, GroupId = groupId, LocationId = locationId, ScheduleId = scheduleId, }; var newOccurrenceService = new AttendanceOccurrenceService(newContext); newOccurrenceService.Add(occurrence); newContext.SaveChanges(); // Query for the new occurrence using original context. occurrence = occurrenceService.Get(occurrence.Id); } } // If we still don't have an occurrence record (i.e. validation failed) return null if (occurrence == null) { return(null); } // Query for existing attendance record Attendance attendance = null; if (personAliasId.HasValue) { attendance = occurrence.Attendees .FirstOrDefault(a => a.PersonAliasId.HasValue && a.PersonAliasId.Value == personAliasId.Value); } // If an attendance record doesn't exist for the occurrence, add a new record if (attendance == null) { attendance = ((RockContext)Context).Attendances.Create(); { attendance.Occurrence = occurrence; attendance.OccurrenceId = occurrence.Id; attendance.PersonAliasId = personAliasId; }; Add(attendance); } // Update details of the attendance (do not overwrite an existing value with an empty value) if (campusId.HasValue) { attendance.CampusId = campusId.Value; } if (deviceId.HasValue) { attendance.DeviceId = deviceId.Value; } if (searchTypeValueId.HasValue) { attendance.SearchTypeValueId = searchTypeValueId; } if (searchValue.IsNotNullOrWhiteSpace()) { attendance.SearchValue = searchValue; } if (checkedInByPersonAliasId.HasValue) { attendance.CheckedInByPersonAliasId = checkedInByPersonAliasId.Value; } if (searchResultGroupId.HasValue) { attendance.SearchResultGroupId = searchResultGroupId; } if (attendanceCodeId.HasValue) { attendance.AttendanceCodeId = attendanceCodeId; } attendance.StartDateTime = checkinDateTime; attendance.DidAttend = true; return(attendance); }