/// <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);
        }
Esempio n. 2
0
        /// <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;
        }