private static List <GroupLocationScheduleCount> UpdateCache() { var output = new List <GroupLocationScheduleCount>(); RockContext rockContext = new RockContext(); AttendanceOccurrenceService attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var attendances = attendanceOccurrenceService.Queryable() .Where(ao => ao.OccurrenceDate == RockDateTime.Today) .SelectMany(ao => ao.Attendees) .Where(a => a.EndDateTime == null) .GroupBy(a => new { a.Occurrence.GroupId, a.Occurrence.LocationId, a.Occurrence.ScheduleId }) .ToList(); foreach (var attendance in attendances) { var glsc = new GroupLocationScheduleCount() { GroupId = attendance.Key.GroupId ?? 0, LocationId = attendance.Key.LocationId ?? 0, ScheduleId = attendance.Key.ScheduleId ?? 0, PersonIds = attendance.Select(a => a.PersonAlias?.PersonId ?? 0).ToList(), InRoomPersonIds = attendance.Where(a => a.DidAttend == true).Select(a => a.PersonAlias?.PersonId ?? 0).ToList() }; output.Add(glsc); } RockCache.AddOrUpdate(cacheKey, null, output, RockDateTime.Now.AddMinutes(10), Constants.CACHE_TAG); return(output); }
/// <summary> /// Gets the occurrence items. /// </summary> private AttendanceOccurrence GetOccurrence(RockContext rockContext, Group group, DateTime date, bool allowAdd) { var occurrenceService = new AttendanceOccurrenceService(rockContext); var occurrence = occurrenceService.Get(date.Date, group.Id, null, group.ScheduleId); // If an occurrence date was included, but no occurrence was found with that date, and new // occurrences can be added, create a new one if (occurrence == null && allowAdd) { // Create a new occurrence record and return it occurrence = new AttendanceOccurrence { Group = group, GroupId = group.Id, OccurrenceDate = date.Date, LocationId = null, ScheduleId = group.ScheduleId, }; occurrenceService.Add(occurrence); return(occurrence); } return(occurrence); }
public BlockActionResult SaveSchedule(PersonScheduleSignupDataBag schedule) { using (var rockContext = new RockContext()) { var groupId = new GroupService(rockContext).GetNoTracking(schedule.GroupGuid).Id; var locationId = new LocationService(rockContext).GetNoTracking(schedule.LocationGuid).Id; var scheduleId = new ScheduleService(rockContext).GetNoTracking(schedule.ScheduleGuid).Id; var attendanceOccurrence = new AttendanceOccurrenceService(rockContext).GetOrAdd(schedule.ScheduledDateTime.DateTime, groupId, locationId, scheduleId); var personAlias = new PersonAliasService(rockContext).Get(CurrentPersonPrimaryAliasId); var attendanceService = new AttendanceService(rockContext); var attendance = attendanceService.ScheduledPersonAddPending(CurrentPersonId, attendanceOccurrence.Id, personAlias); if (attendance == null) { return(ActionBadRequest("Failed to schedule that particular date. Please try again.")); } rockContext.SaveChanges(); attendanceService.ScheduledPersonConfirm(attendance.Id); rockContext.SaveChanges(); return(ActionOk()); } }
/// <summary> /// Initializes the services. /// </summary> /// <param name="rockContext">The rock context.</param> private void InitializeServices(RockContext rockContext) { _systemCommunicationService = new SystemCommunicationService(rockContext); _groupService = new GroupService(rockContext); _groupMemberService = new GroupMemberService(rockContext); _attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); }
/// <summary> /// Handles the Delete event of the gOccurrences control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="RowEventArgs"/> instance containing the event data.</param> protected void gOccurrences_Delete(object sender, RowEventArgs e) { var rockContext = new RockContext(); var occurenceService = new AttendanceOccurrenceService(rockContext); var attendanceService = new AttendanceService(rockContext); var occurrence = occurenceService.Get(e.RowKeyId); if (occurrence != null) { var locationId = occurrence.LocationId; string errorMessage; if (!occurenceService.CanDelete(occurrence, out errorMessage)) { mdGridWarning.Show(errorMessage, ModalAlertType.Alert); return; } // Delete the attendees for this occurrence since it is not a cascading delete var attendees = attendanceService.Queryable().Where(a => a.OccurrenceId == occurrence.Id); rockContext.BulkDelete <Attendance>(attendees); occurenceService.Delete(occurrence); rockContext.SaveChanges(); if (locationId.HasValue) { Rock.CheckIn.KioskLocationAttendance.Remove(locationId.Value); } } BindGrid(); }
/// <summary> /// Gets the attendee data (for use in the grid and chart). /// </summary> /// <param name="rockContext">The RockContext</param> /// <returns>A list of <see cref="RSVPAttendee"/> objects representing the attendees of an occurrence.</returns> private List <RSVPAttendee> GetAttendees(RockContext rockContext) { List <RSVPAttendee> attendees = new List <RSVPAttendee>(); List <int> existingAttendanceRecords = new List <int>(); int?occurrenceId = PageParameter(PageParameterKey.OccurrenceId).AsIntegerOrNull(); if ((occurrenceId != null) && (occurrenceId != 0)) { // Add RSVP responses for anyone who has an attendance record, already. var occurrenceService = new AttendanceOccurrenceService(rockContext); var occurrence = occurrenceService.Get(occurrenceId.Value); var sortedAttendees = occurrence.Attendees.OrderBy(a => a.PersonAlias.Person.LastName).ThenBy(a => a.PersonAlias.Person.FirstName); foreach (var attendee in sortedAttendees) { RSVPAttendee rsvp = new RSVPAttendee(); rsvp.PersonId = attendee.PersonAlias.PersonId; rsvp.NickName = attendee.PersonAlias.Person.NickName; rsvp.LastName = attendee.PersonAlias.Person.LastName; rsvp.Accept = (attendee.RSVP == Rock.Model.RSVP.Yes); rsvp.Decline = (attendee.RSVP == Rock.Model.RSVP.No); rsvp.DeclineReason = attendee.DeclineReasonValueId; rsvp.DeclineNote = attendee.Note; attendees.Add(rsvp); existingAttendanceRecords.Add(attendee.PersonAlias.PersonId); } } return(attendees); }
public virtual HttpResponseMessage CanSchedulePerson(int personId, int attendanceOccurrenceId, int?fromAttendanceOccurrenceId = null) { var rockContext = new RockContext(); var attendanceService = new AttendanceService(rockContext); var attendanceOccurrenceInfo = new AttendanceOccurrenceService(rockContext).GetSelect(attendanceOccurrenceId, s => new { s.ScheduleId, s.OccurrenceDate }); if (attendanceOccurrenceInfo == null) { return(new HttpResponseMessage(HttpStatusCode.NotFound)); } var scheduleId = attendanceOccurrenceInfo.ScheduleId; var occurrenceDate = attendanceOccurrenceInfo.OccurrenceDate; // Only count occurrences with active locations and active schedules as conflicting. var conflictingScheduledAttendancesQuery = attendanceService.Queryable().WhereDeducedIsActive(); if (fromAttendanceOccurrenceId.HasValue) { // if person was dragged from one occurrence to another, we can exclude both source and target occurrences when detecting conflicts conflictingScheduledAttendancesQuery = conflictingScheduledAttendancesQuery .Where(c => (c.OccurrenceId != attendanceOccurrenceId) && (c.OccurrenceId != fromAttendanceOccurrenceId.Value)); } else { // if person was dragged from resources to an occurrence, we can exclude the target occurrences when detecting conflicts conflictingScheduledAttendancesQuery = conflictingScheduledAttendancesQuery .Where(c => c.OccurrenceId != attendanceOccurrenceId); } // a conflict would be if the same person is requested/scheduled for another attendance within the same ScheduleId/Date conflictingScheduledAttendancesQuery = conflictingScheduledAttendancesQuery.Where(c => c.PersonAlias.PersonId == personId && (c.RequestedToAttend == true || c.ScheduledToAttend == true) && c.Occurrence.ScheduleId == scheduleId && c.Occurrence.OccurrenceDate == occurrenceDate); if (conflictingScheduledAttendancesQuery.Any()) { var person = new PersonService(rockContext).Get(personId); var firstConflict = conflictingScheduledAttendancesQuery.Select(s => new { GroupName = s.Occurrence.Group.Name, LocationName = s.Occurrence.Location.Name }).FirstOrDefault(); return(ControllerContext.Request.CreateErrorResponse( HttpStatusCode.BadRequest, $"{person} cannot be scheduled due a scheduling conflict with {firstConflict?.GroupName} in the {firstConflict?.LocationName}.")); } return(new HttpResponseMessage(HttpStatusCode.OK)); }
private void LoadRegistration() { var rockContext = new RockContext(); var groupService = new GroupService(rockContext); var attendanceService = new AttendanceService(rockContext); var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); // get list of groups of this type var groups = groupService.Queryable() .Where(g => g.GroupTypeId == _groupType.Id && g.IsActive == true) .ToList(); var groupIds = groups.Select(g => g.Id).ToList(); // get listing of possible attendance for groups of this type var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(GetAttributeValue("DateRange") ?? "-1||"); var attendanceOccurrences = attendanceOccurrenceService.Queryable() .Where(a => a.GroupId.HasValue && groupIds.Contains(a.GroupId.Value) && a.OccurrenceDate >= dateRange.Start.Value && a.OccurrenceDate <= dateRange.End.Value && a.LocationId == _location.Id) .Distinct() .ToList(); _schedules = attendanceOccurrences.Select(a => new ScheduleResult { Group = a.Group, Schedule = a.Schedule, Date = a.OccurrenceDate }) .Distinct() .ToList(); var occurrenceIds = attendanceOccurrences.Select(o => o.Id).ToList(); // get personal schedules (things you already signed up for) _personalSchedules = attendanceService.Queryable() .Where(a => occurrenceIds.Contains(a.OccurrenceId) && a.PersonAlias.PersonId == CurrentPersonId && a.RSVP == RSVP.Yes) .Select(a => new ScheduleResult { Group = a.Occurrence.Group, Schedule = a.Occurrence.Schedule, Date = a.StartDateTime }) .Distinct() .ToList(); rptScheduleDates.DataSource = _schedules.Select(s => s.Date.Date).Distinct(); rptScheduleDates.DataBind(); }
/// <summary> /// Handles the SaveClick event of the mdMovePerson control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void mdMovePerson_SaveClick(object sender, EventArgs e) { var attendanceId = ddlMovePersonSelectAttendance.SelectedValueAsId(); if (attendanceId == null) { return; } var rockContext = new RockContext(); var attendanceService = new AttendanceService(rockContext); var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var attendance = attendanceService.Get(attendanceId.Value); if (attendance == null) { return; } var selectedOccurrenceDate = attendance.Occurrence.OccurrenceDate; var selectedScheduleId = ddlMovePersonSchedule.SelectedValueAsId(); var selectedLocationId = lpMovePersonLocation.SelectedValueAsId(); var selectedGroupId = ddlMovePersonGroup.SelectedValueAsId(); if (!selectedLocationId.HasValue || !selectedGroupId.HasValue || !selectedScheduleId.HasValue) { return; } var location = NamedLocationCache.Get(selectedLocationId.Value); var locationFirmRoomThreshold = location?.FirmRoomThreshold; if (locationFirmRoomThreshold.HasValue) { // The totalAttended is the number of people still checked in (not people who have been checked-out) // not counting the current person who may already be checked in, // + the person we are trying to move var locationCount = attendanceService.GetByDateOnLocationAndSchedule(selectedOccurrenceDate, selectedLocationId.Value, selectedScheduleId.Value) .Where(a => a.EndDateTime == null && a.PersonAlias.PersonId != attendance.PersonAlias.PersonId).Count(); if ((locationCount + 1) >= locationFirmRoomThreshold.Value) { nbMovePersonLocationFull.Text = $"The {location} has reached its hard threshold capacity and cannot be used for check-in."; nbMovePersonLocationFull.Visible = true; return; } } var newRoomsOccurrence = attendanceOccurrenceService.GetOrAdd(selectedOccurrenceDate, selectedGroupId, selectedLocationId, selectedScheduleId); attendance.OccurrenceId = newRoomsOccurrence.Id; rockContext.SaveChanges(); mdMovePerson.Hide(); BindGrid(); }
/// <summary> /// Binds the grid and chart with attendee data. /// </summary> private void BindAttendeeGridAndChart(bool isExporting = false) { using (var rockContext = new RockContext()) { int?occurrenceId = PageParameter(PageParameterKey.OccurrenceId).AsIntegerOrNull(); if ((occurrenceId == null) || (occurrenceId == 0)) { occurrenceId = hfNewOccurrenceId.Value.AsIntegerOrNull(); } if ((occurrenceId != null) && (occurrenceId != 0)) { var occurrenceService = new AttendanceOccurrenceService(rockContext); var occurrence = occurrenceService.Get(occurrenceId.Value); gAttendees.ColumnsOfType <RockTemplateField>() .First(c => c.HeaderText == "Decline Reason") .Visible = occurrence.ShowDeclineReasons; gAttendees.ColumnsOfType <RockTemplateField>() .First(c => c.HeaderText == "Decline Note") .Visible = occurrence.ShowDeclineReasons; } gAttendees.ColumnsOfType <BoolField>() .First(c => c.HeaderText == "Accept") .Visible = isExporting; gAttendees.ColumnsOfType <RockLiteralField>() .First(c => c.HeaderText == "Decline Reason") .Visible = isExporting; gAttendees.ColumnsOfType <BoolField>() .First(c => c.HeaderText == "Decline") .Visible = isExporting; var attendees = GetAttendees(rockContext); int acceptCount = attendees.Where(a => a.Accept).Count(); int declineCount = attendees.Where(a => a.Decline).Count(); int noResponseCount = attendees.Count() - acceptCount - declineCount; RegisterDoughnutChartScript(acceptCount, declineCount, noResponseCount); _availableDeclineReasons = null; GetAvailableDeclineReasons(); gAttendees.DataSource = attendees; gAttendees.DataBind(); if (attendees.Count() < 1) { lbSave.Visible = false; } else { lbSave.Visible = true; } } }
/// <summary> /// Gets the data items to be included in the grid. /// </summary> /// <param name="groupId"></param> private List <RSVPListOccurrence> GetGroupRSVP(int groupId) { DateTime? fromDateTime = drpDates.LowerValue; DateTime? toDateTime = drpDates.UpperValue; List <int> locationIds = new List <int>(); List <int> scheduleIds = new List <int>(); // Location Filter if (ddlLocation.Visible) { int?locationId = ddlLocation.SelectedValue.AsIntegerOrNull(); if (locationId.HasValue) { locationIds.Add(locationId.Value); } } //// Schedule Filter //if ( ddlSchedule.Visible ) //{ // int? scheduleId = ddlSchedule.SelectedValue.AsIntegerOrNull(); // if ( scheduleId.HasValue ) // { // scheduleIds.Add( scheduleId.Value ); // } //} var rockContext = new RockContext(); var groupService = new GroupService(rockContext); var group = groupService.Get(groupId); //int invitedCount = group.ActiveMembers().Count(); // Get all the occurrences for this group for the selected dates, location and schedule var occurrences = new AttendanceOccurrenceService(rockContext) .GetGroupOccurrences(group, fromDateTime, toDateTime, locationIds, scheduleIds) .Select(o => new RSVPListOccurrence(o)) .ToList(); // Sort the occurrences List <RSVPListOccurrence> sortedOccurrences = null; if (gRSVPItems.SortProperty != null) { sortedOccurrences = occurrences.AsQueryable().Sort(gRSVPItems.SortProperty).ToList(); } else { sortedOccurrences = occurrences.OrderByDescending(a => a.OccurrenceDate).ThenByDescending(a => a.StartTime).ToList(); } return(sortedOccurrences); }
public void AttendanceOccurrenceDateKeyJoinsCorrectly() { var expectedRecordCount = 15; var year = 2016; using (var rockContext = new RockContext()) { var minDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, year); var maxDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, year); var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var dates = new List <DateTime>(); DateTime GetUniqueDate() { var date = TestDataHelper.GetRandomDateInRange(minDateValue, maxDateValue); while (dates.Contains(date)) { date = TestDataHelper.GetRandomDateInRange(minDateValue, maxDateValue); } dates.Add(date); return(date); } for (var i = 0; i < 15; i++) { var attendanceOccurrence = BuildAttendanceOccurrence(rockContext, GetUniqueDate()); attendanceOccurrenceService.Add(attendanceOccurrence); } rockContext.SaveChanges(); } using (var rockContext = new RockContext()) { var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var attendanceOccurrences = attendanceOccurrenceService. Queryable(). Where(i => i.ForeignKey == attendanceOccurrenceForeignKey). Where(i => i.OccurrenceSourceDate.CalendarYear == year); Assert.AreEqual(expectedRecordCount, attendanceOccurrences.Count()); var actualAttendanceOccurrences = attendanceOccurrences.First(); var actualOccurrenceSourceDate = actualAttendanceOccurrences.OccurrenceSourceDate; Assert.IsNotNull(actualOccurrenceSourceDate); } }
/// <summary> /// Initializes a new instance of the <see cref="GroupAttendedTransaction"/> class. /// </summary> /// <param name="entry">The entry.</param> public GroupAttendedTransaction(DbEntityEntry entry) { if (entry.State != EntityState.Deleted) { // Get the attendance record var attendance = entry.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 = entry.State == EntityState.Added; // If not an add, check previous DidAttend value if (!valid) { var dbProperty = entry.Property("DidAttend"); if (dbProperty != null) { // Only use changes where DidAttend was previously not true valid = !(dbProperty.OriginalValue as bool? ?? false); } } if (valid) { var occ = attendance.Occurrence; if (occ == null) { occ = new AttendanceOccurrenceService(new RockContext()).Get(attendance.OccurrenceId); } if (occ != null) { // Save the values GroupId = occ.GroupId; AttendanceDateTime = occ.OccurrenceDate; PersonAliasId = attendance.PersonAliasId; if (occ.Group != null) { GroupTypeId = occ.Group.GroupTypeId; } } } } } }
/// <summary> /// Gets the occurrences query. /// </summary> /// <param name="includeSchedule">if set to <c>true</c> [include schedule].</param> /// <returns></returns> private IQueryable <AttendanceOccurrence> GetOccurrencesQuery(bool includeSchedule = true) { // get the occurrences for SelectedDate with Groups var occurrenceQuery = new AttendanceOccurrenceService(_rockContext) .Queryable() .AsNoTracking() .Where(o => o.OccurrenceDate == SelectedDate.Value && o.GroupId.HasValue); // if filtering by schedule if (includeSchedule && SelectedSchedule.IsNotNullOrWhiteSpace()) { var scheduleId = SelectedSchedule.AsInteger(); occurrenceQuery = occurrenceQuery.Where(o => o.ScheduleId.HasValue && o.ScheduleId.Value == scheduleId); } return(occurrenceQuery); }
internal static AttendanceOccurrence GetOccurrenceForLocation(RockContext rockContext, Location location) { if (IsSubRoom(location)) { location = location.ParentLocation; } AttendanceOccurrenceService attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var occurrences = attendanceOccurrenceService.Queryable() .Where(o => o.OccurrenceDate == RockDateTime.Now.Date && o.LocationId == location.Id).ToList(); var volunteerOccurrences = occurrences.Where(o => OccurrenceCache.GetVolunteerOccurrences().Select(oc => oc.GroupId).Contains(o.GroupId ?? 0)).FirstOrDefault(); if (volunteerOccurrences != null) { return(volunteerOccurrences); } return(null); }
public List <GroupOccurrenceResponse> GetFutureGroupOccurrences(int groupId, DateTime?toDateTime = null, string locationIds = null, string scheduleIds = null) { using (var rockContext = new RockContext()) { rockContext.Configuration.ProxyCreationEnabled = false; var group = new GroupService(rockContext).Get(groupId); var occurrences = new AttendanceOccurrenceService(rockContext) .GetFutureGroupOccurrences(group, toDateTime, locationIds, scheduleIds); var response = new List <GroupOccurrenceResponse>(); foreach (var occurrence in occurrences) { response.Add(new GroupOccurrenceResponse(occurrence)); } return(response); } }
public void AttendanceOccurrenceDateKeySavesCorrectly() { var rockContext = new RockContext(); var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var attendanceOccurrence = BuildAttendanceOccurrence(rockContext, Convert.ToDateTime("3/15/2010")); attendanceOccurrenceService.Add(attendanceOccurrence); rockContext.SaveChanges(); var attendanceOccurrenceId = attendanceOccurrence.Id; // We're bypassing the model because the model doesn't user the AttendanceOccurrenceDateKey from the database, // but it still needs to be correct for inner joins to work correctly. var result = rockContext.Database. SqlQuery <int>($"SELECT OccurrenceDateKey FROM AttendanceOccurrence WHERE Id = {attendanceOccurrenceId}").First(); Assert.AreEqual(20100315, result); }
private static AttendanceOccurrence GetOrAddOccurrence(RockContext rockContext, Group group, Event ebEvent) { var occurrenceService = new AttendanceOccurrenceService(rockContext); // Get all the occurrences for this group for the selected dates, location and schedule var occurrences = occurrenceService.GetGroupOccurrences(group, ebEvent.Start.Local.Date, null, new List <int>(), new List <int>()).ToList(); var occ = occurrences.FirstOrDefault(o => o.OccurrenceDate.Date.Equals(ebEvent.Start.Local.Date)); if (occ == null) { occ = new AttendanceOccurrence { GroupId = group.Id, OccurrenceDate = ebEvent.Start.Local.Date }; occurrenceService.Add(occ); } return(occ); }
/// <summary> /// Gets a list of future occurrences within the date range of the specified offset with RSVP responses for a <see cref="Group"/>. Eager loads Attendees and /// attached Person records. /// </summary> /// <param name="group">The <see cref="Group"/>.</param> /// <param name="offsetDays">The number of days prior to the RSVP occurrence that a reminder should be sent.</param> /// <param name="rockContext">The <see cref="RockContext"/>.</param> /// <returns>A list of <see cref="AttendanceOccurrence"/> objects.</returns> private List <AttendanceOccurrence> GetOccurrencesForGroup(Group group, int offsetDays, RockContext rockContext) { // Calculate correct date range from the RSVP Offset. DateTime startDate = DateTime.Today.AddDays(offsetDays); DateTime endDate = startDate.AddDays(1); // This can't use WithNoTracking because the sms service tries to access the PrimaryAliasId // which links to the Aliases property, but when we try to at the Aliases property to the include list // we get an "The RelatedEnd with role name X has already been loaded" error because it has already // been loaded with the PersonAlias object, however removing the AsNoTracking() resolves this issue. // you can read more about it here: // https://stackoverflow.com/questions/46038016/the-relatedend-with-role-name-x-has-already-been-loaded var rsvpOccurrences = new AttendanceOccurrenceService(rockContext) .Queryable("Attendees,Attendees.PersonAlias.Person") .Where(o => o.GroupId == group.Id) .Where(o => o.OccurrenceDate >= startDate) // OccurrenceDate must be greater than startDate (the beginning of the day from the offset). .Where(o => o.OccurrenceDate < endDate) // OccurrenceDate must be less than endDate (the end of the day from the offset). .Where(o => o.Attendees.Where(a => a.RSVP == RSVP.Yes).Any()) // Occurrence must have attendees who responded "Yes". .ToList(); return(rsvpOccurrences); }
/// <summary> /// Removes the groups with attendence data. /// </summary> /// <param name="occurrences">The occurrences.</param> /// <param name="startDate">The start date.</param> /// <param name="endDate">The end date.</param> /// <param name="rockContext">The rock context.</param> private void RemoveGroupsWithAttendenceData(Dictionary <int, List <DateTime> > occurrences, DateTime startDate, DateTime endDate, RockContext rockContext) { var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var occurrencesWithAttendence = attendanceOccurrenceService .Queryable() .AsNoTracking() .DateInRange(startDate, endDate) .GroupIdsInList(occurrences.Keys.ToList()) .HasScheduleId() .HasAttendeesOrDidNotOccur() .Select(a => new { GroupId = a.GroupId.Value, a.OccurrenceDate }) .Distinct() .ToList(); foreach (var occurrence in occurrencesWithAttendence) { occurrences[occurrence.GroupId].RemoveAll(d => d.Date == occurrence.OccurrenceDate.Date); } }
/// <summary> /// Executes the specified context. /// </summary> /// <param name="context">The context.</param> public virtual void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; var groupType = GroupTypeCache.Get(dataMap.GetString("GroupType").AsGuid()); int attendanceRemindersSent = 0; int errorCount = 0; var errorMessages = new List <string>(); if (groupType.TakesAttendance && groupType.SendAttendanceReminder) { // Get the occurrence dates that apply var dates = new List <DateTime>(); dates.Add(RockDateTime.Today); try { string[] reminderDays = dataMap.GetString("SendReminders").Split(','); foreach (string reminderDay in reminderDays) { if (reminderDay.Trim().IsNotNullOrWhiteSpace()) { var reminderDate = RockDateTime.Today.AddDays(0 - Convert.ToInt32(reminderDay)); if (!dates.Contains(reminderDate)) { dates.Add(reminderDate); } } } } catch { } var rockContext = new RockContext(); var groupService = new GroupService(rockContext); var groupMemberService = new GroupMemberService(rockContext); var scheduleService = new ScheduleService(rockContext); var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var startDate = dates.Min(); var endDate = dates.Max().AddDays(1); // Find all 'occurrences' for the groups that occur on the affected dates var occurrences = new Dictionary <int, List <DateTime> >(); foreach (var group in groupService .Queryable("Schedule").AsNoTracking() .Where(g => g.GroupTypeId == groupType.Id && g.IsActive && g.Schedule != null && g.Members.Any(m => m.GroupMemberStatus == GroupMemberStatus.Active && m.GroupRole.IsLeader && m.Person.Email != null && m.Person.Email != String.Empty))) { // Add the group occurrences.Add(group.Id, new List <DateTime>()); // Check for a iCal schedule if (!string.IsNullOrWhiteSpace(group.Schedule.iCalendarContent)) { // If schedule has an iCal schedule, get occurrences between first and last dates foreach (var occurrence in group.Schedule.GetOccurrences(startDate, endDate)) { var startTime = occurrence.Period.StartTime.Value; if (dates.Contains(startTime.Date)) { occurrences[group.Id].Add(startTime); } } } else { // if schedule does not have an iCal, then check for weekly schedule and calculate occurrences starting with first attendance or current week if (group.Schedule.WeeklyDayOfWeek.HasValue) { foreach (var date in dates) { if (date.DayOfWeek == group.Schedule.WeeklyDayOfWeek.Value) { var startTime = date; if (group.Schedule.WeeklyTimeOfDay.HasValue) { startTime = startTime.Add(group.Schedule.WeeklyTimeOfDay.Value); } occurrences[group.Id].Add(startTime); } } } } } // Remove any occurrences during group type exclusion date ranges foreach (var exclusion in groupType.GroupScheduleExclusions) { if (exclusion.Start.HasValue && exclusion.End.HasValue) { foreach (var keyVal in occurrences) { foreach (var occurrenceDate in keyVal.Value.ToList()) { if (occurrenceDate >= exclusion.Start.Value && occurrenceDate < exclusion.End.Value.AddDays(1)) { keyVal.Value.Remove(occurrenceDate); } } } } } // Remove any 'occurrences' that already have attendance data entered foreach (var occurrence in attendanceOccurrenceService .Queryable().AsNoTracking() .Where(a => a.OccurrenceDate >= startDate && a.OccurrenceDate < endDate && a.GroupId.HasValue && occurrences.Keys.Contains(a.GroupId.Value) && a.ScheduleId.HasValue && (a.Attendees.Any() || (a.DidNotOccur.HasValue && a.DidNotOccur.Value))) .Select(a => new { GroupId = a.GroupId.Value, a.OccurrenceDate }) .Distinct() .ToList()) { occurrences[occurrence.GroupId].RemoveAll(d => d.Date == occurrence.OccurrenceDate.Date); } // Get the groups that have occurrences var groupIds = occurrences.Where(o => o.Value.Any()).Select(o => o.Key).ToList(); // Get the leaders of those groups var leaders = groupMemberService .Queryable("Group,Person").AsNoTracking() .Where(m => groupIds.Contains(m.GroupId) && m.GroupMemberStatus == GroupMemberStatus.Active && m.GroupRole.IsLeader && m.Person.Email != null && m.Person.Email != string.Empty) .ToList(); // Loop through the leaders foreach (var leader in leaders) { foreach (var group in occurrences.Where(o => o.Key == leader.GroupId)) { var mergeObjects = Rock.Lava.LavaHelper.GetCommonMergeFields(null, leader.Person); mergeObjects.Add("Person", leader.Person); mergeObjects.Add("Group", leader.Group); mergeObjects.Add("Occurrence", group.Value.Max()); var recipients = new List <RecipientData>(); recipients.Add(new RecipientData(leader.Person.Email, mergeObjects)); var emailMessage = new RockEmailMessage(dataMap.GetString("SystemEmail").AsGuid()); emailMessage.SetRecipients(recipients); var errors = new List <string>(); emailMessage.Send(out errors); if (errors.Any()) { errorCount += errors.Count; errorMessages.AddRange(errors); } else { attendanceRemindersSent++; } } } } context.Result = string.Format("{0} attendance reminders sent", attendanceRemindersSent); if (errorMessages.Any()) { StringBuilder sb = new StringBuilder(); sb.AppendLine(); sb.Append(string.Format("{0} Errors: ", errorCount)); errorMessages.ForEach(e => { sb.AppendLine(); sb.Append(e); }); string errors = sb.ToString(); context.Result += errors; var exception = new Exception(errors); HttpContext context2 = HttpContext.Current; ExceptionLogService.LogException(exception, context2); throw exception; } }
/// <summary> /// Executes the specified workflow. /// </summary> /// <param name="rockContext">The rock context.</param> /// <param name="action">The workflow action.</param> /// <param name="entity">The entity.</param> /// <param name="errorMessages">The error messages.</param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages) { var checkInState = GetCheckInState(entity, out errorMessages); if (checkInState != null) { bool loadAll = GetAttributeValue(action, "LoadAll").AsBoolean(); foreach (var family in checkInState.CheckIn.GetFamilies(true)) { foreach (var person in family.GetPeople(!loadAll)) { foreach (var groupType in person.GetGroupTypes(!loadAll).ToList()) { var kioskGroupType = checkInState.Kiosk.ActiveGroupTypes(checkInState.ConfiguredGroupTypes) .Where(g => g.GroupType.Id == groupType.GroupType.Id) .FirstOrDefault(); if (kioskGroupType != null) { foreach (var group in groupType.GetGroups(!loadAll)) { var closedGroupLocationIds = new AttendanceOccurrenceService(rockContext) .Queryable() .AsNoTracking() .Where(o => o.GroupId == group.Group.Id && o.OccurrenceDate == RockDateTime.Today) .WhereAttributeValue(rockContext, "rocks.kfs.OccurrenceClosed", "True") .Select(l => l.LocationId) .ToList(); var loadBalance = group.Group.GetAttributeValue("rocks.kfs.LoadBalanceLocations").AsBoolean(); if (loadBalance && loadAll) { group.Locations.Clear(); } var locationAttendance = new Dictionary <CheckInLocation, int>(); foreach (var kioskGroup in kioskGroupType.KioskGroups .Where(g => g.Group.Id == group.Group.Id && g.IsCheckInActive) .ToList()) { foreach (var kioskLocation in kioskGroup.KioskLocations.Where(l => l.IsCheckInActive && l.IsActiveAndNotFull && !closedGroupLocationIds.Contains(l.Location.Id))) { if (!group.Locations.Any(l => l.Location.Id == kioskLocation.Location.Id)) { var checkInLocation = new CheckInLocation(); checkInLocation.Location = kioskLocation.Location.Clone(false); checkInLocation.Location.CopyAttributesFrom(kioskLocation.Location); checkInLocation.CampusId = kioskLocation.CampusId; checkInLocation.Order = kioskLocation.Order; locationAttendance.Add(checkInLocation, KioskLocationAttendance.Get(checkInLocation.Location.Id).CurrentCount); } } } if (loadBalance) { var sortedLocationAttendance = locationAttendance.ToList(); sortedLocationAttendance.Sort((x, y) => x.Key.Location.Name.CompareTo(y.Key.Location.Name)); sortedLocationAttendance.Sort((x, y) => x.Value.CompareTo(y.Value)); var order = 0; foreach (var checkInLocationPair in sortedLocationAttendance) { var checkInLocation = checkInLocationPair.Key; checkInLocation.Order = order; group.Locations.Add(checkInLocation); order++; } } else { group.Locations.AddRange(locationAttendance.Select(l => l.Key).ToList()); } } } } } } return(true); } return(false); }
/// <summary> /// Binds the group members grid. /// </summary> protected void BindGrid() { if (_group != null) { lHeading.Text = _group.Name; DateTime? fromDateTime = drpDates.LowerValue; DateTime? toDateTime = drpDates.UpperValue; List <int> locationIds = new List <int>(); List <int> scheduleIds = new List <int>(); // Location Filter if (ddlLocation.Visible) { string locValue = ddlLocation.SelectedValue; if (locValue.StartsWith("P")) { int?parentLocationId = locValue.Substring(1).AsIntegerOrNull(); if (parentLocationId.HasValue) { locationIds = new LocationService(_rockContext) .GetAllDescendents(parentLocationId.Value) .Select(l => l.Id) .ToList(); } } else { int?locationId = locValue.AsIntegerOrNull(); if (locationId.HasValue) { locationIds.Add(locationId.Value); } } } // Schedule Filter if (ddlSchedule.Visible && ddlSchedule.SelectedValue != "0") { scheduleIds.Add(ddlSchedule.SelectedValueAsInt() ?? 0); } // Get all the occurrences for this group for the selected dates, location and schedule var occurrences = new AttendanceOccurrenceService(_rockContext) .GetGroupOccurrences(_group, fromDateTime, toDateTime, locationIds, scheduleIds) .Select(o => new AttendanceListOccurrence(o)) .ToList(); var locationService = new LocationService(_rockContext); // Check to see if filtering by campus, and if so, only select those occurrences who's // location is associated with that campus (or not associated with any campus) int?campusId = bddlCampus.SelectedValueAsInt(); if (campusId.HasValue) { // If campus filter is selected, load all the descendent locations for each campus into a dictionary var locCampus = new Dictionary <int, int>(); foreach (var campus in CampusCache.All().Where(c => c.LocationId.HasValue)) { locCampus.AddOrIgnore(campus.LocationId.Value, campus.Id); foreach (var locId in locationService.GetAllDescendentIds(campus.LocationId.Value)) { locCampus.AddOrIgnore(locId, campus.Id); } } // Using that dictionary, set the campus id for each occurrence foreach (var occ in occurrences) { if (occ.LocationId.HasValue && locCampus.ContainsKey(occ.LocationId.Value)) { occ.CampusId = locCampus[occ.LocationId.Value]; } } // Remove the occurrences that are associated with another campus occurrences = occurrences .Where(o => !o.CampusId.HasValue || o.CampusId.Value == campusId.Value) .ToList(); } // Update the Parent Location path foreach (int parentLocationId in occurrences .Where(o => o.ParentLocationId.HasValue) .Select(o => o.ParentLocationId.Value) .Distinct()) { string parentLocationPath = locationService.GetPath(parentLocationId); foreach (var occ in occurrences .Where(o => o.ParentLocationId.HasValue && o.ParentLocationId.Value == parentLocationId)) { occ.ParentLocationPath = parentLocationPath; } } // Sort the occurrences SortProperty sortProperty = gOccurrences.SortProperty; List <AttendanceListOccurrence> sortedOccurrences = null; if (sortProperty != null) { if (sortProperty.Property == "LocationPath,LocationName") { if (sortProperty.Direction == SortDirection.Ascending) { sortedOccurrences = occurrences.OrderBy(o => o.ParentLocationPath).ThenBy(o => o.LocationName).ToList(); } else { sortedOccurrences = occurrences.OrderByDescending(o => o.ParentLocationPath).ThenByDescending(o => o.LocationName).ToList(); } } else { sortedOccurrences = occurrences.AsQueryable().Sort(sortProperty).ToList(); } } else { sortedOccurrences = occurrences.OrderByDescending(a => a.OccurrenceDate).ThenByDescending(a => a.StartTime).ToList(); } gOccurrences.DataSource = sortedOccurrences; gOccurrences.DataBind(); } }
/// <summary> /// Builds the status board. /// </summary> private void BuildStatusBoard() { lGroupStatusTableHTML.Text = string.Empty; int numberOfWeeks = GetSelectedNumberOfWeeks(); List <int> selectedGroupIds = GetSelectedGroupIds(); var rockContext = new RockContext(); var groupsQuery = new GroupService(rockContext).GetByIds(selectedGroupIds).Where(a => a.GroupType.IsSchedulingEnabled == true); nbGroupsWarning.Visible = false; if (!groupsQuery.Any()) { nbGroupsWarning.Text = "Please select at least one group."; nbGroupsWarning.NotificationBoxType = NotificationBoxType.Warning; nbGroupsWarning.Visible = true; return; } var groupLocationService = new GroupLocationService(rockContext); var groupLocationsQuery = groupLocationService.Queryable().Where(a => selectedGroupIds.Contains(a.GroupId) && a.Group.GroupType.IsSchedulingEnabled == true); // get all the schedules that are in use by at least one of the GroupLocations var groupsScheduleList = groupLocationsQuery.SelectMany(a => a.Schedules).Distinct().AsNoTracking().ToList(); if (!groupsScheduleList.Any()) { nbGroupsWarning.Text = "The selected groups don't have any location schedules configured."; nbGroupsWarning.NotificationBoxType = NotificationBoxType.Warning; nbGroupsWarning.Visible = true; return; } // get the next N sundayDates List <DateTime> sundayDateList = GetSundayDateList(numberOfWeeks); // build the list of scheduled times for the next n weeks List <ScheduleOccurrenceDate> scheduleOccurrenceDateList = new List <ScheduleOccurrenceDate>(); var currentDate = RockDateTime.Today; foreach (var sundayDate in sundayDateList) { foreach (var schedule in groupsScheduleList) { var sundayWeekStart = sundayDate.AddDays(-6); // get all the occurrences for the selected week for this scheduled (It could be more than once a week if it is a daily scheduled, or it might not be in the selected week if it is every 2 weeks, etc) var scheduledDateTimeList = schedule.GetScheduledStartTimes(sundayWeekStart, sundayDate.AddDays(1)); foreach (var scheduledDateTime in scheduledDateTimeList) { if (scheduledDateTime >= currentDate) { scheduleOccurrenceDateList.Add(new ScheduleOccurrenceDate { Schedule = schedule, ScheduledDateTime = scheduledDateTime }); } } } } scheduleOccurrenceDateList = scheduleOccurrenceDateList.OrderBy(a => a.ScheduledDateTime).ToList(); var latestOccurrenceDate = sundayDateList.Max(); var scheduledOccurrencesQuery = new AttendanceOccurrenceService(rockContext).Queryable().Where(a => a.GroupId.HasValue && a.LocationId.HasValue && a.ScheduleId.HasValue && selectedGroupIds.Contains(a.GroupId.Value)); scheduledOccurrencesQuery = scheduledOccurrencesQuery.Where(a => a.OccurrenceDate >= currentDate && a.OccurrenceDate <= latestOccurrenceDate); var occurrenceScheduledAttendancesList = scheduledOccurrencesQuery.Select(ao => new { Occurrence = ao, ScheduledAttendees = ao.Attendees.Where(a => a.RequestedToAttend == true || a.ScheduledToAttend == true).Select(a => new { ScheduledPerson = a.PersonAlias.Person, a.RequestedToAttend, a.ScheduledToAttend, a.RSVP }) }).ToList(); StringBuilder sbTable = new StringBuilder(); // start of table sbTable.AppendLine("<table class='table schedule-status-board js-schedule-status-board'>"); sbTable.AppendLine("<thead class='schedule-status-board-header js-schedule-status-board-header'>"); sbTable.AppendLine("<tr>"); var tableHeaderLavaTemplate = @" {%- comment -%}empty column for group/location names{%- endcomment -%} <th scope='col'></th> {% for scheduleOccurrenceDate in ScheduleOccurrenceDateList %} <th scope='col'> <span class='date'>{{ scheduleOccurrenceDate.ScheduledDateTime | Date:'MMM d, yyyy' }}</span> <br /> <span class='day-time'>{{ scheduleOccurrenceDate.Schedule.Name }}</span> </th> {% endfor %} "; var headerMergeFields = new Dictionary <string, object> { { "ScheduleOccurrenceDateList", scheduleOccurrenceDateList } }; string tableHeaderHtml = tableHeaderLavaTemplate.ResolveMergeFields(headerMergeFields); sbTable.Append(tableHeaderHtml); sbTable.AppendLine("</tr>"); sbTable.AppendLine("</thead>"); var groupLocationsList = groupsQuery.Where(g => g.GroupLocations.Any()).OrderBy(a => a.Order).ThenBy(a => a.Name).Select(g => new { Group = g, LocationScheduleCapacitiesList = g.GroupLocations.OrderBy(gl => gl.Order).ThenBy(gl => gl.Location.Name).Select(a => new { ScheduleCapacitiesList = a.GroupLocationScheduleConfigs.Select(sc => new ScheduleCapacities { ScheduleId = sc.ScheduleId, MinimumCapacity = sc.MinimumCapacity, DesiredCapacity = sc.DesiredCapacity, MaximumCapacity = sc.MaximumCapacity }), a.Location }).ToList() }).ToList(); var columnsCount = scheduleOccurrenceDateList.Count() + 1; foreach (var groupLocations in groupLocationsList) { var group = groupLocations.Group; StringBuilder sbGroupLocations = new StringBuilder(); sbGroupLocations.AppendLine(string.Format("<tbody class='group-locations js-group-locations' data-group-id='{0}' data-locations-expanded='1'>", group.Id)); // group header row sbGroupLocations.AppendLine("<tr class='group-heading js-group-header thead-dark clickable' >"); sbGroupLocations.AppendLine(string.Format("<th></th><th colspan='{0}'><i class='fa fa-chevron-down'></i> {1}</th>", columnsCount - 1, group.Name)); sbGroupLocations.AppendLine("</tr>"); // group/schedule+locations var locationScheduleCapacitiesList = groupLocations.LocationScheduleCapacitiesList; foreach (var locationScheduleCapacities in locationScheduleCapacitiesList) { var location = locationScheduleCapacities.Location; var scheduleCapacitiesLookup = locationScheduleCapacities.ScheduleCapacitiesList.ToDictionary(k => k.ScheduleId, v => v); sbGroupLocations.AppendLine("<tr class='location-row js-location-row'>"); sbGroupLocations.AppendLine(string.Format("<td class='location' scope='row' data-location-id='{0}'><div>{1}</div></td>", location.Id, location.Name)); foreach (var scheduleOccurrenceDate in scheduleOccurrenceDateList) { var capacities = scheduleCapacitiesLookup.GetValueOrNull(scheduleOccurrenceDate.Schedule.Id) ?? new ScheduleCapacities(); var scheduleLocationStatusHtmlFormat = @"<ul class='location-scheduled-list' data-capacity-min='{1}' data-capacity-desired='{2}' data-capacity-max='{3}' data-scheduled-count='{4}'> {0} </ul>"; StringBuilder sbScheduledListHtml = new StringBuilder(); var occurrenceScheduledAttendances = occurrenceScheduledAttendancesList .FirstOrDefault(ao => ao.Occurrence.OccurrenceDate == scheduleOccurrenceDate.OccurrenceDate && ao.Occurrence.GroupId == groupLocations.Group.Id && ao.Occurrence.ScheduleId == scheduleOccurrenceDate.Schedule.Id && ao.Occurrence.LocationId == location.Id); int scheduledCount = 0; if (occurrenceScheduledAttendances != null && occurrenceScheduledAttendances.ScheduledAttendees.Any()) { // sort so that it is Yes, then Pending, then Denied var scheduledPersonList = occurrenceScheduledAttendances .ScheduledAttendees .OrderBy(a => a.RSVP == RSVP.Yes ? 0 : 1) .ThenBy(a => (a.RSVP == RSVP.Maybe || a.RSVP == RSVP.Unknown) ? 0 : 1) .ThenBy(a => a.RSVP == RSVP.No ? 0 : 1) .ThenBy(a => a.ScheduledPerson.LastName) .ToList(); foreach (var scheduledPerson in scheduledPersonList) { ScheduledAttendanceItemStatus status = ScheduledAttendanceItemStatus.Pending; if (scheduledPerson.RSVP == RSVP.No) { status = ScheduledAttendanceItemStatus.Declined; } else if (scheduledPerson.ScheduledToAttend == true) { status = ScheduledAttendanceItemStatus.Confirmed; } sbScheduledListHtml.AppendLine(string.Format("<li class='slot person {0}' data-status='{0}'><i class='status-icon'></i><span class='person-name'>{1}</span></li>", status.ConvertToString(false).ToLower(), scheduledPerson.ScheduledPerson)); } scheduledCount = scheduledPersonList.Where(a => a.RSVP != RSVP.No).Count(); } if (capacities.DesiredCapacity.HasValue && scheduledCount < capacities.DesiredCapacity.Value) { var countNeeded = capacities.DesiredCapacity.Value - scheduledCount; sbScheduledListHtml.AppendLine(string.Format("<li class='slot persons-needed empty-slot'>{0} {1} needed</li>", countNeeded, "person".PluralizeIf(countNeeded != 1))); // add empty slots if we are under the desired count (not including the slot for the 'persons-needed' li) var emptySlotsToAdd = countNeeded - 1; while (emptySlotsToAdd > 0) { sbScheduledListHtml.AppendLine("<li class='slot empty-slot'></li>"); emptySlotsToAdd--; } } var scheduledLocationsStatusHtml = string.Format(scheduleLocationStatusHtmlFormat, sbScheduledListHtml, capacities.MinimumCapacity, capacities.DesiredCapacity, capacities.MaximumCapacity, scheduledCount); sbGroupLocations.AppendLine(string.Format("<td class='schedule-location js-schedule-location' data-schedule-id='{0}'><div>{1}</div></td>", scheduleOccurrenceDate.Schedule.Id, scheduledLocationsStatusHtml)); } sbGroupLocations.AppendLine("</tr>"); } sbGroupLocations.AppendLine("</tbody>"); sbTable.Append(sbGroupLocations.ToString()); } // closing divs for main header sbTable.AppendLine("</tr>"); sbTable.AppendLine("</thead>"); // closing divs for table sbTable.AppendLine("</table>"); lGroupStatusTableHTML.Text = sbTable.ToString(); }
private void BindGrid() { gReport.Visible = false; nbNotification.Visible = false; RockContext rockContext = new RockContext(); AttendanceOccurrenceService attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); AttendanceService attendanceService = new AttendanceService(rockContext); LocationService locationService = new LocationService(rockContext); ScheduleService scheduleService = new ScheduleService(rockContext); var location = lpLocation.Location; if (location == null || dpDate.SelectedDate == null) { return; } //Set the name of the export List <string> locationNameList = new List <string>(); var locationForExport = location; while (true) { if (locationForExport == null) { break; } locationNameList.Add(locationForExport.Name); locationForExport = locationForExport.ParentLocation; } locationNameList.Reverse(); gReport.ExportTitleName = dpDate.SelectedDate.Value.ToString("MM/dd/yyyy") + " -- "; if (tgChildLocations.Checked) { gReport.ExportTitleName += " Child Locations of: "; } gReport.ExportTitleName += string.Join(" > ", locationNameList); var schedule = scheduleService.Get(spSchedule.SelectedValueAsId() ?? 0); if (schedule != null) { gReport.ExportTitleName += " (" + schedule.Name + ")"; } var fileName = dpDate.SelectedDate.Value.ToString("MM.dd.yyyy") + (tgChildLocations.Checked ? "_ChildLocationsOf_" : "_") + location.Name; if (schedule != null) { fileName += "_" + schedule.Name; } gReport.ExportFilename = fileName; //Get child locations if needed var locationIds = new List <int> { location.Id }; if (tgChildLocations.Checked) { List <Location> childLocations = GetChildLocations(location); locationIds.AddRange(childLocations.Select(l => l.Id)); } var attendanceOccurrencesQry = attendanceOccurrenceService .Queryable() .Where(ao => ao.OccurrenceDate == (dpDate.SelectedDate ?? RockDateTime.Now)) .Where(ao => locationIds.Contains(ao.LocationId ?? 0)) .Where(ao => ao.Group != null && ao.Schedule != null); var scheduleId = spSchedule.SelectedValueAsId(); if (scheduleId != null) { attendanceOccurrencesQry = attendanceOccurrencesQry.Where(ao => ao.ScheduleId == scheduleId); } var attendanceOccurrences = attendanceOccurrencesQry .Select(ao => ao.Id) .ToList(); var attendances = attendanceService.Queryable("PersonAlias, PersonAlias.Person, Occurrence, Occurrence.Group, Occurrence.Location, Occurrence.Schedule, Device") .Where(a => attendanceOccurrences.Contains(a.OccurrenceId)) .ToList(); if (!attendances.Any()) { nbNotification.Visible = true; nbNotification.Text = "Could not find any attendances with these parameters"; return; } var records = new List <AttendanceRecord>(); var volunteerGroupIds = KioskCountUtility.GetVolunteerGroupIds(); foreach (var attendance in attendances) { var record = new AttendanceRecord { PersonId = attendance.PersonAlias.Person.Id, PersonName = attendance.PersonAlias.Person.FullNameReversed, Age = attendance.PersonAlias.Person.Age, Schedule = attendance.Occurrence.Schedule.Name, Location = attendance.Occurrence.Location.Name, Group = attendance.Occurrence.Group.Name, CheckInTime = attendance.CreatedDateTime, EntryTime = attendance.StartDateTime, ExitTime = attendance.EndDateTime, DidAttend = attendance.DidAttend, IsVolunteer = volunteerGroupIds.Contains(attendance.Occurrence.GroupId ?? 0), Device = attendance.Device != null ? attendance.Device.Name : "Room Scanner" }; if (attendance.ForeignId != null) { var subLocation = locationService.Get(attendance.ForeignId ?? 0); if (subLocation != null) { record.SubLocation = subLocation.Name; } } if (record.CheckInTime >= record.EntryTime && record.Device != "Room Scanner") { record.EntryTime = null; } records.Add(record); } records = records .OrderBy(r => r.CheckInTime) .ToList(); gReport.Visible = true; gReport.DataSource = records; gReport.DataBind(); }
/// <summary> /// Save RSVP response data from grid (to Attendance records). /// </summary> protected bool SaveRSVPData() { var attendees = new List <RSVPAttendee>(); foreach (GridViewRow row in gAttendees.Rows) { if (row.RowType == DataControlRowType.DataRow) { RockCheckBox rcbAccept = row.FindControl("rcbAccept") as RockCheckBox; RockCheckBox rcbDecline = row.FindControl("rcbDecline") as RockCheckBox; DataDropDownList rddlDeclineReason = row.FindControl("rddlDeclineReason") as DataDropDownList; RockTextBox tbDeclineNote = row.FindControl("tbDeclineNote") as RockTextBox; int declineReason = int.Parse(rddlDeclineReason.SelectedValue); string declineNote = tbDeclineNote.Text; attendees.Add( new RSVPAttendee() { Accept = rcbAccept.Checked, Decline = rcbDecline.Checked, DeclineNote = declineNote, DeclineReason = declineReason, PersonId = ( int )gAttendees.DataKeys[row.RowIndex].Value } ); } } using (var rockContext = new RockContext()) { var occurrenceService = new AttendanceOccurrenceService(rockContext); var attendanceService = new AttendanceService(rockContext); var personAliasService = new PersonAliasService(rockContext); AttendanceOccurrence occurrence = null; int?groupId = PageParameter(PageParameterKey.GroupId).AsIntegerOrNull(); int?occurrenceId = PageParameter(PageParameterKey.OccurrenceId).AsIntegerOrNull(); if ((occurrenceId == null) || (occurrenceId == 0)) { occurrenceId = hfNewOccurrenceId.Value.AsIntegerOrNull(); if ((occurrenceId == null) || (occurrenceId == 0)) { throw new Exception("The AttendanceOccurrence does not exist."); } } occurrence = occurrenceService.Get(occurrenceId.Value); var existingAttendees = occurrence.Attendees.ToList(); foreach (var attendee in attendees) { var attendance = existingAttendees .Where(a => a.PersonAlias.PersonId == attendee.PersonId) .FirstOrDefault(); if (attendance == null) { int?personAliasId = personAliasService.GetPrimaryAliasId(attendee.PersonId); if (personAliasId.HasValue) { attendance = new Attendance(); attendance.PersonAliasId = personAliasId; attendance.StartDateTime = occurrence.Schedule != null && occurrence.Schedule.HasSchedule() ? occurrence.OccurrenceDate.Date.Add(occurrence.Schedule.StartTimeOfDay) : occurrence.OccurrenceDate; occurrence.Attendees.Add(attendance); } } if (attendance != null) { if (attendee.Accept) { var groupMember = occurrence.Group.Members.Where(gm => gm.PersonId == attendee.PersonId).FirstOrDefault(); if (groupMember == null) { groupMember = new GroupMember(); groupMember.PersonId = attendee.PersonId; groupMember.GroupId = occurrence.Group.Id; groupMember.GroupRoleId = occurrence.Group.GroupType.DefaultGroupRoleId ?? 0; new GroupMemberService(rockContext).Add(groupMember); rockContext.SaveChanges(); } // only set the RSVP and Date if the value is changing if (attendance.RSVP != Rock.Model.RSVP.Yes) { attendance.RSVPDateTime = DateTime.Now; attendance.RSVP = Rock.Model.RSVP.Yes; } attendance.Note = string.Empty; attendance.DeclineReasonValueId = null; } else if (attendee.Decline) { // only set the RSVP and Date if the value is changing if (attendance.RSVP != Rock.Model.RSVP.No) { attendance.RSVPDateTime = DateTime.Now; attendance.RSVP = Rock.Model.RSVP.No; } attendance.Note = attendee.DeclineNote; if (attendee.DeclineReason != 0) { attendance.DeclineReasonValueId = attendee.DeclineReason; } } else { attendance.RSVPDateTime = null; attendance.RSVP = Rock.Model.RSVP.Unknown; attendance.Note = string.Empty; attendance.DeclineReasonValueId = null; } } } rockContext.SaveChanges(); if (occurrence.LocationId.HasValue) { Rock.CheckIn.KioskLocationAttendance.Remove(occurrence.LocationId.Value); } } return(true); }
public void Execute(IJobExecutionContext context) { JobDataMap dataMap = context.JobDetail.JobDataMap; var rockContext = new RockContext(); InteractionChannelService channelService = new InteractionChannelService(rockContext); InteractionComponentService componentService = new InteractionComponentService(rockContext); InteractionService interactionService = new InteractionService(rockContext); ScheduleService scheduleService = new ScheduleService(rockContext); LocationService locationService = new LocationService(rockContext); AttendanceService attendanceService = new AttendanceService(rockContext); AttendanceOccurrenceService attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); GroupService groupService = new GroupService(rockContext); // Load the channel InteractionChannelCache channel = InteractionChannelCache.Get(dataMap.GetString("InteractionChannel").AsGuid()); // Setup int campusLocationTypeId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.LOCATION_TYPE_CAMPUS).Id; var groupType = GroupTypeCache.Get(dataMap.GetString("GroupType").AsGuid()); var groupLocations = groupService.GetByGroupTypeId(groupType.Id).Where(g => g.IsActive == true).SelectMany(g => g.GroupLocations).ToList(); string operation = !string.IsNullOrWhiteSpace(dataMap.GetString("Operation")) ? dataMap.GetString("Operation") : null; // Fetch the job so we can get the last run date/time int jobId = Convert.ToInt16(context.JobDetail.Description); var jobService = new ServiceJobService(rockContext); var job = jobService.Get(jobId); DateTime lastRun = job?.LastSuccessfulRunDateTime ?? DateTime.MinValue; var componentCampusMapping = dataMap.GetString("ComponentCampusMapping").AsDictionaryOrNull(); DateRange dateRange = Rock.Web.UI.Controls.SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(dataMap.GetString("DateRange") ?? "-1||"); // Flip the component campus mapping around and translate to ids Dictionary <int, List <int> > campusComponentIds = new Dictionary <int, List <int> >(); foreach (CampusCache campus in CampusCache.All()) { var componentNames = componentCampusMapping.Where(ccm => ccm.Value == campus.Name).Select(c => c.Key.ToLower()); campusComponentIds[campus.Id] = componentService.Queryable().Where(cs => componentNames.Contains(cs.Name.ToLower()) && cs.ChannelId == channel.Id).Select(c => c.Id).ToList(); } foreach (GroupLocation gl in groupLocations) { if (gl.Group.CampusId.HasValue) { Location location = gl.Location; List <int> componentIds = campusComponentIds[gl.Group.CampusId.Value]; foreach (Schedule schedule in gl.Schedules) { var occurrences = schedule.GetOccurrences(dateRange.Start.Value, dateRange.End.Value); foreach (var occurrence in occurrences) { DateTime startDate = occurrence.Period.StartTime.Value; DateTime endDate = occurrence.Period.EndTime.Value; var peopleAttended = interactionService.Queryable().Where( i => componentIds.Contains(i.InteractionComponentId) && i.InteractionDateTime <= endDate && i.InteractionEndDateTime >= startDate && i.PersonAliasId != null && (i.CreatedDateTime > lastRun || i.PersonalDevice.ModifiedDateTime > lastRun || i.PersonalDevice.CreatedDateTime > lastRun) && (operation == null || i.Operation == operation) ).Select(i => i.PersonAliasId).Distinct(); int newAttendance = 0; var occurrenceModel = attendanceOccurrenceService.Get(occurrence.Period.StartTime.Value.Date, gl.GroupId, location.Id, schedule.Id); // Make sure we don't already have an attendance Record var existingAttendees = attendanceOccurrenceService.Queryable().Where(ao => DbFunctions.TruncateTime(ao.OccurrenceDate) == occurrence.Period.StartTime.Value.Date && ao.ScheduleId == schedule.Id && ao.GroupId == gl.GroupId && ao.LocationId == location.Id).SelectMany(a => a.Attendees).Where(a => a.DidAttend == true).Select(a => a.PersonAliasId); foreach (int personAliasId in peopleAttended.Except(existingAttendees)) { // Check to see if an occurrence exists already if (occurrenceModel == null) { var attendance = attendanceService.AddOrUpdate(personAliasId, occurrence.Period.StartTime.Value, gl.GroupId, location.Id, schedule.Id, gl.Group.CampusId); attendance.EndDateTime = occurrence.Period?.EndTime?.Value; attendance.DidAttend = true; attendance.CampusId = gl.Group.CampusId; occurrenceModel = attendance.Occurrence; } else { Attendance attendance = new Attendance(); attendance.PersonAliasId = personAliasId; attendance.OccurrenceId = occurrenceModel.Id; attendance.StartDateTime = occurrence.Period.StartTime.Value; attendance.EndDateTime = occurrence.Period?.EndTime?.Value; attendance.DidAttend = true; attendance.CampusId = gl.Group.CampusId; attendanceService.Add(attendance); } newAttendance++; } if (newAttendance > 0) { rockContext.SaveChanges(); context.Result += string.Format("{0} people attended {1} on {2}.\n", newAttendance, gl.Group.Campus.Name, occurrence.Period.StartTime.Value.ToString("MM/dd/yyyy h:mm tt")); } } } } } }
/// <summary> /// Binds the Attendance Occurrences ( Which shows the Location for the Attendance Occurrence for the selected Group + DateTime + Location ). /// groupScheduler.js will populate these with the scheduled resources /// </summary> private void BindAttendanceOccurrences() { var occurrenceSundayDate = hfOccurrenceSundayDate.Value.AsDateTime().Value.Date; var occurrenceSundayWeekStartDate = occurrenceSundayDate.AddDays(-6); // make sure we don't let them schedule dates in the past if (occurrenceSundayWeekStartDate <= RockDateTime.Today) { occurrenceSundayWeekStartDate = RockDateTime.Today; } var scheduleId = rblSchedule.SelectedValueAsId(); var rockContext = new RockContext(); var occurrenceSchedule = new ScheduleService(rockContext).GetNoTracking(scheduleId ?? 0); if (occurrenceSchedule == null) { btnAutoSchedule.Visible = false; return; } // get all the occurrences for the selected week for this scheduled (It could be more than once a week if it is a daily scheduled, or it might not be in the selected week if it is every 2 weeks, etc) var scheduleOccurrenceDateTimeList = occurrenceSchedule.GetScheduledStartTimes(occurrenceSundayWeekStartDate, occurrenceSundayDate.AddDays(1)); if (!scheduleOccurrenceDateTimeList.Any()) { btnAutoSchedule.Visible = false; return; } var occurrenceDateList = scheduleOccurrenceDateTimeList.Select(a => a.Date).ToList(); btnAutoSchedule.Visible = true; var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); var selectedGroupLocationIds = cblGroupLocations.SelectedValuesAsInt; List <AttendanceOccurrence> missingAttendanceOccurrenceList = attendanceOccurrenceService.CreateMissingAttendanceOccurrences(occurrenceDateList, scheduleId.Value, selectedGroupLocationIds); if (missingAttendanceOccurrenceList.Any()) { attendanceOccurrenceService.AddRange(missingAttendanceOccurrenceList); rockContext.SaveChanges(); } IQueryable <AttendanceOccurrenceService.AttendanceOccurrenceGroupLocationScheduleConfigJoinResult> attendanceOccurrenceGroupLocationScheduleConfigQuery = attendanceOccurrenceService.AttendanceOccurrenceGroupLocationScheduleConfigJoinQuery(occurrenceDateList, scheduleId.Value, selectedGroupLocationIds); var attendanceOccurrencesList = attendanceOccurrenceGroupLocationScheduleConfigQuery.AsNoTracking() .OrderBy(a => a.GroupLocation.Order).ThenBy(a => a.GroupLocation.Location.Name) .Select(a => new AttendanceOccurrenceRowItem { LocationName = a.AttendanceOccurrence.Location.Name, GroupLocationOrder = a.GroupLocation.Order, LocationId = a.AttendanceOccurrence.LocationId, Schedule = a.AttendanceOccurrence.Schedule, OccurrenceDate = a.AttendanceOccurrence.OccurrenceDate, AttendanceOccurrenceId = a.AttendanceOccurrence.Id, CapacityInfo = new CapacityInfo { MinimumCapacity = a.GroupLocationScheduleConfig.MinimumCapacity, DesiredCapacity = a.GroupLocationScheduleConfig.DesiredCapacity, MaximumCapacity = a.GroupLocationScheduleConfig.MaximumCapacity } }).ToList(); var groupId = hfGroupId.Value.AsInteger(); var attendanceOccurrencesOrderedList = attendanceOccurrencesList.OrderBy(a => a.ScheduledDateTime).ThenBy(a => a.GroupLocationOrder).ThenBy(a => a.LocationName).ToList(); // if there are any people that signed up with no location preference, add the to a special list of "No Location Preference" occurrences to the top of the list var unassignedLocationOccurrenceList = attendanceOccurrenceService.Queryable() .Where(a => occurrenceDateList.Contains(a.OccurrenceDate) && a.ScheduleId == scheduleId.Value && a.GroupId == groupId && a.LocationId.HasValue == false) .Where(a => a.Attendees.Any(x => x.RequestedToAttend == true || x.ScheduledToAttend == true)) .Select(a => new AttendanceOccurrenceRowItem { LocationName = "No Location Preference", GroupLocationOrder = 0, LocationId = null, Schedule = a.Schedule, OccurrenceDate = a.OccurrenceDate, AttendanceOccurrenceId = a.Id, CapacityInfo = new CapacityInfo() }) .ToList() .OrderBy(a => a.ScheduledDateTime) .ToList(); attendanceOccurrencesOrderedList.InsertRange(0, unassignedLocationOccurrenceList); rptAttendanceOccurrences.DataSource = attendanceOccurrencesOrderedList; rptAttendanceOccurrences.DataBind(); hfDisplayedOccurrenceIds.Value = attendanceOccurrencesOrderedList.Select(a => a.AttendanceOccurrenceId).ToList().AsDelimited(","); }
/// <summary> /// Creates an AttendanceOccurrence if one doesn't already exist and returns the ID. /// </summary> /// <param name="e">The RowEventArgs of the selected grid row.</param> /// <returns>The ID of an AttendanceOccurrence</returns> private int GetOccurrenceId(RowEventArgs e) { int occurrenceId = e.RowKeyId; if (occurrenceId == 0) { // Find or create occurrence. using (var rockContext = new RockContext()) { HiddenField hfOccurrenceDate = e.Row.FindControl("hfOccurrenceDate") as HiddenField; HiddenField hfGroupId = e.Row.FindControl("hfGroupId") as HiddenField; HiddenField hfScheduleId = e.Row.FindControl("hfScheduleId") as HiddenField; HiddenField hfLocationId = e.Row.FindControl("hfLocationId") as HiddenField; DateTime occurrenceDate = DateTime.Parse(hfOccurrenceDate.Value); int?groupId = hfGroupId.Value.AsIntegerOrNull(); int?scheduleId = hfScheduleId.Value.AsIntegerOrNull(); int?locationId = hfLocationId.Value.AsIntegerOrNull(); var group = new GroupService(rockContext).Get(groupId.Value); var attendanceOccurrenceService = new AttendanceOccurrenceService(rockContext); //If this occurrence has already been created, just return the existing one. var existingOccurrenceQry = attendanceOccurrenceService.Queryable().Where(o => o.OccurrenceDate == occurrenceDate); if (groupId != null) { existingOccurrenceQry = existingOccurrenceQry.Where(o => o.GroupId == groupId); } if (scheduleId != null) { existingOccurrenceQry = existingOccurrenceQry.Where(o => o.ScheduleId == scheduleId); } if (locationId != null) { existingOccurrenceQry = existingOccurrenceQry.Where(o => o.LocationId == locationId); } var existingOccurrences = existingOccurrenceQry.ToList(); if (existingOccurrences.Any()) { occurrenceId = existingOccurrences.FirstOrDefault().Id; } else { //Create new occurrence. var attendanceOccurrence = new AttendanceOccurrence(); if (groupId != null) { attendanceOccurrence.GroupId = groupId; } if (scheduleId != null) { attendanceOccurrence.ScheduleId = scheduleId; } if (locationId != null) { attendanceOccurrence.LocationId = locationId; } attendanceOccurrence.OccurrenceDate = occurrenceDate; attendanceOccurrenceService.Add(attendanceOccurrence); rockContext.SaveChanges(); occurrenceId = attendanceOccurrence.Id; } } return(occurrenceId); } return(occurrenceId); }
/// <summary> /// Creates a new AttendanceOccurrence record. /// </summary> private bool CreateNewOccurrence() { using (var rockContext = new RockContext()) { int?groupId = PageParameter(PageParameterKey.GroupId).AsIntegerOrNull(); var group = new GroupService(rockContext).Get(groupId.Value); //Create new occurrence. var occurrence = new AttendanceOccurrence(); occurrence.Name = tbOccurrenceName.Text; occurrence.GroupId = groupId; if (locpLocation.Location != null) { occurrence.Location = new LocationService(rockContext).Get(locpLocation.Location.Id); occurrence.LocationId = occurrence.Location.Id; } else { occurrence.Location = null; occurrence.LocationId = null; } // The schedule is OK to be null occurrence.ScheduleId = spSchedule.SelectedValueAsId(); if (dpOccurrenceDate.SelectedDate.HasValue) { occurrence.OccurrenceDate = dpOccurrenceDate.SelectedDate.Value; } var occurrenceService = new AttendanceOccurrenceService(rockContext); // If this occurrence has already been created, just use the existing one. var existingOccurrences = occurrenceService.Queryable() .Where(o => o.GroupId == occurrence.GroupId) .Where(o => o.OccurrenceDate == occurrence.OccurrenceDate) .Where(o => o.ScheduleId == occurrence.ScheduleId) .Where(o => o.LocationId == occurrence.LocationId) .ToList(); if (existingOccurrences.Any()) { occurrence = existingOccurrences.FirstOrDefault(); } else { occurrenceService.Add(occurrence); } occurrence.DeclineConfirmationMessage = heDeclineMessage.Text; occurrence.AcceptConfirmationMessage = heAcceptMessage.Text; occurrence.ShowDeclineReasons = rcbShowDeclineReasons.Checked; var selectedDeclineReasons = new List <string>(); foreach (ListItem listItem in rcblAvailableDeclineReasons.Items) { if (listItem.Selected) { selectedDeclineReasons.Add(listItem.Value); } } occurrence.DeclineReasonValueIds = selectedDeclineReasons.AsDelimited(","); rockContext.SaveChanges(); occurrence = occurrenceService.Get(occurrence.Id); hfNewOccurrenceId.Value = occurrence.Id.ToString(); ShowDetails(rockContext, occurrence.Id, group); return(true); } }