/// <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); }
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)); } }
private LaunchMemberAttendedGroupWorkflow.Message GetLaunchMemberAttendedGroupWorkflowMessage() { var launchMemberAttendedGroupWorkflowMsg = new LaunchMemberAttendedGroupWorkflow.Message(); if (State != EntityContextState.Deleted) { // Get the attendance record var attendance = Entity as Attendance; // If attendance record is valid and the DidAttend is true (not null or false) if (attendance != null && (attendance.DidAttend == true)) { // Save for all adds bool valid = State == EntityContextState.Added; // If not an add, check previous DidAttend value if (!valid) { // Only use changes where DidAttend was previously not true valid = !( bool )Entry.OriginalValues.GetReadOnlyValueOrDefault("DidAttend", false); } if (valid) { var occ = attendance.Occurrence; if (occ == null) { occ = new AttendanceOccurrenceService(new RockContext()).Get(attendance.OccurrenceId); } if (occ != null) { // Save the values launchMemberAttendedGroupWorkflowMsg.GroupId = occ.GroupId; launchMemberAttendedGroupWorkflowMsg.AttendanceDateTime = occ.OccurrenceDate; launchMemberAttendedGroupWorkflowMsg.PersonAliasId = attendance.PersonAliasId; if (occ.Group != null) { launchMemberAttendedGroupWorkflowMsg.GroupTypeId = occ.Group.GroupTypeId; } } } } } return(launchMemberAttendedGroupWorkflowMsg); }
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> /// 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); }
/// <summary> /// Method that will be called on an entity immediately before the item is saved by context /// </summary> protected override void PreSave() { PersonAttendanceHistoryChangeList = new History.HistoryChangeList(); _isDeleted = State == EntityContextState.Deleted; bool previousDidAttendValue; bool previouslyDeclined; if (State == EntityContextState.Added) { previousDidAttendValue = false; previouslyDeclined = false; } else { // get original values so we can detect whether the value changed previousDidAttendValue = ( bool )Entry.OriginalValues.GetReadOnlyValueOrDefault("DidAttend", false); previouslyDeclined = (Entry.OriginalValues.GetReadOnlyValueOrDefault("RSVP", null) as RSVP? ) == RSVP.No; } // if the record was changed to Declined, queue a GroupScheduleCancellationTransaction in PostSaveChanges _declinedScheduledAttendance = (previouslyDeclined == false) && Entity.IsScheduledPersonDeclined(); if (previousDidAttendValue == false && Entity.DidAttend == true) { var launchMemberAttendedGroupWorkflowMsg = GetLaunchMemberAttendedGroupWorkflowMessage(); launchMemberAttendedGroupWorkflowMsg.Send(); } var attendance = this.Entity; if (State == EntityContextState.Modified) { preSavePersonAliasId = attendance.PersonAliasId; var originalOccurrenceId = ( int? )OriginalValues[nameof(attendance.OccurrenceId)]; if (originalOccurrenceId.HasValue && attendance.OccurrenceId != originalOccurrenceId.Value) { var attendanceOccurrenceService = new AttendanceOccurrenceService(this.RockContext); var originalOccurrence = attendanceOccurrenceService.GetNoTracking(originalOccurrenceId.Value); var currentOccurrence = attendanceOccurrenceService.GetNoTracking(attendance.OccurrenceId); if (originalOccurrence != null && currentOccurrence != null) { if (originalOccurrence.GroupId != currentOccurrence.GroupId) { History.EvaluateChange(PersonAttendanceHistoryChangeList, "Group", originalOccurrence.Group?.Name, currentOccurrence.Group?.Name); } if (originalOccurrence.ScheduleId.HasValue && currentOccurrence.ScheduleId.HasValue && originalOccurrence.ScheduleId.Value != currentOccurrence.ScheduleId.Value) { History.EvaluateChange(PersonAttendanceHistoryChangeList, "Schedule", NamedScheduleCache.Get(originalOccurrence.ScheduleId.Value)?.Name, NamedScheduleCache.Get(currentOccurrence.ScheduleId.Value)?.Name); } if (originalOccurrence.LocationId.HasValue && currentOccurrence.LocationId.HasValue && originalOccurrence.LocationId.Value != currentOccurrence.LocationId.Value) { History.EvaluateChange(PersonAttendanceHistoryChangeList, "Location", NamedLocationCache.Get(originalOccurrence.LocationId.Value)?.Name, NamedLocationCache.Get(currentOccurrence.LocationId.Value)?.Name); } } } } else if (State == EntityContextState.Deleted) { preSavePersonAliasId = ( int? )OriginalValues[nameof(attendance.PersonAliasId)]; PersonAttendanceHistoryChangeList.AddChange(History.HistoryVerb.Delete, History.HistoryChangeType.Record, "Attendance"); } base.PreSave(); }