/// <summary> /// Creates and returns a list of missing attendance occurrences for the specified dates, scheduleId and groupLocationIds. /// These will be new AttendanceOccurrence records that haven't been saved to the database yet. /// </summary> /// <param name="occurrenceDateList">The occurrence date list.</param> /// <param name="scheduleId">The schedule identifier.</param> /// <param name="groupLocationIds">The group location ids.</param> /// <returns></returns> public List <AttendanceOccurrence> CreateMissingAttendanceOccurrences(List <DateTime> occurrenceDateList, int scheduleId, List <int> groupLocationIds) { if (!groupLocationIds.Any()) { return(new List <AttendanceOccurrence>()); } var groupLocationQuery = new GroupLocationService(this.Context as RockContext).GetByIds(groupLocationIds); int?groupId = null; int?locationId = null; if (groupLocationIds.Count == 1) { // if there is only one group location, we can optimize the attendanceOccurrencesQuery to use a simpler LINQ expression var groupLocationInfo = groupLocationQuery.Select(a => new { a.GroupId, a.LocationId }).FirstOrDefault(); groupId = groupLocationInfo.GroupId; locationId = groupLocationInfo?.LocationId; } List <AttendanceOccurrence> missingAttendanceOccurrenceList = new List <AttendanceOccurrence>(); foreach (var occurrenceDate in occurrenceDateList) { var attendanceOccurrencesQuery = this.Queryable() .Where(a => a.GroupId.HasValue && a.LocationId.HasValue && a.ScheduleId == scheduleId && a.OccurrenceDate == occurrenceDate); if (groupId.HasValue && locationId.HasValue) { // since we have just group location id (and date and schedule), we just have to check if the attendance occurrence exists attendanceOccurrencesQuery = attendanceOccurrencesQuery.Where(a => a.GroupId == groupId.Value && a.LocationId == locationId.Value); if (attendanceOccurrencesQuery.Any()) { continue; } else { missingAttendanceOccurrenceList.Add(new AttendanceOccurrence { GroupId = groupId.Value, LocationId = locationId.Value, ScheduleId = scheduleId, OccurrenceDate = occurrenceDate }); } continue; } else { attendanceOccurrencesQuery = attendanceOccurrencesQuery.Where(a => groupLocationQuery.Any(gl => gl.GroupId == a.GroupId && gl.LocationId == a.LocationId)); List <AttendanceOccurrence> missingAttendanceOccurrencesForOccurrenceDate = groupLocationQuery.Where(gl => !attendanceOccurrencesQuery.Any(ao => ao.LocationId == gl.LocationId && ao.GroupId == gl.GroupId)) .Select(gl => new { gl.GroupId, gl.LocationId, }) .AsNoTracking() .ToList() .Select(gl => new AttendanceOccurrence { GroupId = gl.GroupId, LocationId = gl.LocationId, ScheduleId = scheduleId, OccurrenceDate = occurrenceDate }).ToList(); if (missingAttendanceOccurrencesForOccurrenceDate.Any()) { missingAttendanceOccurrenceList.AddRange(missingAttendanceOccurrencesForOccurrenceDate); } } } return(missingAttendanceOccurrenceList); }
/// <summary> /// Gets the expression. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="serviceInstance">The service instance.</param> /// <param name="parameterExpression">The parameter expression.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override Expression GetExpression( Type entityType, IService serviceInstance, ParameterExpression parameterExpression, string selection ) { var values = selection.Split( '|' ); ComparisonType comparisonType = values[0].ConvertToEnum<ComparisonType>( ComparisonType.EqualTo ); string postalCode = values[1]; var familyGroupTypeGuid = Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY.AsGuid(); var groupLocationQry = new GroupLocationService( ( RockContext ) serviceInstance.Context ).Queryable(); switch ( comparisonType ) { case ComparisonType.EqualTo: groupLocationQry = groupLocationQry.Where( gl => gl.Location.PostalCode == postalCode ); break; case ComparisonType.NotEqualTo: groupLocationQry = groupLocationQry.Where( gl => gl.Location.PostalCode != postalCode ); break; case ComparisonType.StartsWith: groupLocationQry = groupLocationQry.Where( gl => gl.Location.PostalCode.StartsWith( postalCode ) ); break; case ComparisonType.Contains: groupLocationQry = groupLocationQry.Where( gl => gl.Location.PostalCode.Contains( postalCode ) ); break; case ComparisonType.DoesNotContain: groupLocationQry = groupLocationQry.Where( gl => !gl.Location.PostalCode.Contains( postalCode ) ); break; case ComparisonType.IsBlank: groupLocationQry = groupLocationQry .Where( gl => gl.Location.PostalCode == null || gl.Location.PostalCode == string.Empty ); break; case ComparisonType.IsNotBlank: groupLocationQry = groupLocationQry .Where( gl => gl.Location.PostalCode != null && gl.Location.PostalCode != string.Empty ); break; case ComparisonType.EndsWith: groupLocationQry = groupLocationQry.Where( gl => gl.Location.PostalCode.EndsWith( postalCode ) ); break; default: break; } IQueryable<Rock.Model.Person> qry; var groupMemberQry = groupLocationQry.Select( gl => gl.Group ) .Where( g => g.GroupType.Guid == familyGroupTypeGuid ) .SelectMany( g => g.Members ); // Families which do not have locations need to be added separately if ( comparisonType == ComparisonType.IsBlank || comparisonType == ComparisonType.DoesNotContain || comparisonType == ComparisonType.NotEqualTo ) { var noLocationGroupMembersQry = new GroupService( ( RockContext ) serviceInstance.Context ).Queryable() .Where( g => g.GroupType.Guid == familyGroupTypeGuid && !g.GroupLocations.Any() ) .SelectMany( g => g.Members ); qry = new PersonService( ( RockContext ) serviceInstance.Context ).Queryable() .Where( p => groupMemberQry.Any( xx => xx.PersonId == p.Id ) || noLocationGroupMembersQry.Any( xx => xx.PersonId == p.Id ) ); } else { qry = new PersonService( ( RockContext ) serviceInstance.Context ).Queryable() .Where( p => groupMemberQry.Any( xx => xx.PersonId == p.Id ) ); } Expression extractedFilterExpression = FilterExpressionExtractor.Extract<Rock.Model.Person>( qry, parameterExpression, "p" ); return extractedFilterExpression; }