/// <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 rockContext = (RockContext)serviceInstance.Context;

            string[] selectionValues = selection.Split('|');
            if (selectionValues.Length < 3)
            {
                return(null);
            }

            DateTime?startDate     = selectionValues[0].AsDateTime();
            DateTime?endDate       = selectionValues[1].AsDateTime();
            var      accountGuids  = selectionValues[2].Split(',').Select(a => a.AsGuid()).ToList();
            var      accountIdList = new FinancialAccountService((RockContext)serviceInstance.Context).GetByGuids(accountGuids).Select(a => a.Id).ToList();

            int transactionTypeContributionId = Rock.Web.Cache.DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id;

            var financialTransactionsQry = new FinancialTransactionService(rockContext).Queryable()
                                           .Where(xx => xx.TransactionTypeValueId == transactionTypeContributionId);

            if (accountIdList.Any())
            {
                if (accountIdList.Count == 1)
                {
                    int accountId = accountIdList.First();
                    financialTransactionsQry = financialTransactionsQry.Where(xx => xx.TransactionDetails.Any(a => a.AccountId == accountId));
                }
                else
                {
                    financialTransactionsQry = financialTransactionsQry.Where(xx => xx.TransactionDetails.Any(a => accountIdList.Contains(a.AccountId)));
                }
            }

            var firstContributionDateQry = financialTransactionsQry
                                           .GroupBy(xx => xx.AuthorizedPersonAlias.PersonId)
                                           .Select(ss => new
            {
                PersonId = ss.Key,
                FirstTransactionSundayDate = ss.Min(a => a.SundayDate)
            });

            if (startDate.HasValue)
            {
                firstContributionDateQry = firstContributionDateQry.Where(xx => xx.FirstTransactionSundayDate >= startDate.Value);
            }

            if (endDate.HasValue)
            {
                firstContributionDateQry = firstContributionDateQry.Where(xx => xx.FirstTransactionSundayDate < endDate);
            }

            var innerQry = firstContributionDateQry.Select(xx => xx.PersonId).AsQueryable();

            var qry = new PersonService(rockContext).Queryable()
                      .Where(p => innerQry.Any(xx => xx == p.Id));

            Expression extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, parameterExpression, "p");

            return(extractedFilterExpression);
        }
        /// <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 rockContext = (RockContext)serviceInstance.Context;

            SelectionConfig selectionConfig = SelectionConfig.Parse(selection);

            if (selectionConfig == null)
            {
                return(null);
            }

            DateRange dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(selectionConfig.DelimitedValues);

            int transactionTypeContributionId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id;
            var financialTransactionsQry      = new FinancialTransactionService(rockContext)
                                                .Queryable()
                                                .Where(xx => xx.TransactionTypeValueId == transactionTypeContributionId);

            var accountIdList = new FinancialAccountService(( RockContext )serviceInstance.Context).GetByGuids(selectionConfig.AccountGuids).Select(a => a.Id).ToList();

            if (accountIdList.Any())
            {
                if (accountIdList.Count == 1)
                {
                    int accountId = accountIdList.First();
                    financialTransactionsQry = financialTransactionsQry.Where(xx => xx.TransactionDetails.Any(a => a.AccountId == accountId));
                }
                else
                {
                    financialTransactionsQry = financialTransactionsQry.Where(xx => xx.TransactionDetails.Any(a => accountIdList.Contains(a.AccountId)));
                }
            }

            var firstContributionDateQry = financialTransactionsQry
                                           .GroupBy(xx => xx.AuthorizedPersonAlias.PersonId)
                                           .Select(ss => new
            {
                PersonId             = ss.Key,
                FirstTransactionDate = ss.Min(a => selectionConfig.UseSundayDate == true ? a.SundayDate : a.TransactionDateTime)
            });

            if (dateRange.Start.HasValue)
            {
                firstContributionDateQry = firstContributionDateQry.Where(xx => xx.FirstTransactionDate >= dateRange.Start.Value);
            }

            if (dateRange.End.HasValue)
            {
                firstContributionDateQry = firstContributionDateQry.Where(xx => xx.FirstTransactionDate < dateRange.End.Value);
            }

            var innerQry = firstContributionDateQry.Select(xx => xx.PersonId).AsQueryable();
            var qry      = new PersonService(rockContext).Queryable().Where(p => innerQry.Any(xx => xx == p.Id));

            return(FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, parameterExpression, "p"));
        }
        /// <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 rockContext = (RockContext)serviceInstance.Context;

            string[] selectionValues = selection.Split( '|' );
            if ( selectionValues.Length < 3 )
            {
                return null;
            }

            DateTime? startDate = selectionValues[0].AsDateTime();
            DateTime? endDate = selectionValues[1].AsDateTime();
            var accountGuids = selectionValues[2].Split( ',' ).Select( a => a.AsGuid() ).ToList();
            var accountIdList = new FinancialAccountService( (RockContext)serviceInstance.Context ).GetByGuids( accountGuids ).Select( a => a.Id ).ToList();

            int transactionTypeContributionId = Rock.Web.Cache.DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() ).Id;

            var financialTransactionsQry = new FinancialTransactionService( rockContext ).Queryable()
                .Where( xx => xx.TransactionTypeValueId == transactionTypeContributionId );

            if ( accountIdList.Any() )
            {
                if ( accountIdList.Count == 1 )
                {
                    int accountId = accountIdList.First();
                    financialTransactionsQry = financialTransactionsQry.Where( xx => xx.TransactionDetails.Any( a => a.AccountId == accountId ) );
                }
                else
                {
                    financialTransactionsQry = financialTransactionsQry.Where( xx => xx.TransactionDetails.Any( a => accountIdList.Contains( a.AccountId ) ) );
                }
            }

            var firstContributionDateQry = financialTransactionsQry
                .GroupBy( xx => xx.AuthorizedPersonAlias.PersonId )
                .Select( ss => new
                {
                    PersonId = ss.Key,
                    FirstTransactionDateTime = ss.Min( a => a.TransactionDateTime )
                } );

            if ( startDate.HasValue )
            {
                firstContributionDateQry = firstContributionDateQry.Where( xx => xx.FirstTransactionDateTime >= startDate.Value );
            }

            if ( endDate.HasValue )
            {
                firstContributionDateQry = firstContributionDateQry.Where( xx => xx.FirstTransactionDateTime < endDate );
            }

            var innerQry = firstContributionDateQry.Select( xx => xx.PersonId ).AsQueryable();

            var qry = new PersonService( rockContext ).Queryable()
                .Where( p => innerQry.Any( xx => xx == p.Id ) );

            Expression extractedFilterExpression = FilterExpressionExtractor.Extract<Rock.Model.Person>( qry, parameterExpression, "p" );

            return extractedFilterExpression;
        }
        /// <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 rockContext = (RockContext)serviceInstance.Context;

            string[] selectionValues = selection.Split('|');
            if (selectionValues.Length < 3)
            {
                return(null);
            }

            DateRange dateRange;

            if (selectionValues.Length >= 4)
            {
                string slidingDelimitedValues = selectionValues[3].Replace(',', '|');
                dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(slidingDelimitedValues);
            }
            else
            {
                // if converting from a previous version of the selection
                DateTime?startDate = selectionValues[0].AsDateTime();
                DateTime?endDate   = selectionValues[1].AsDateTime();
                dateRange = new DateRange(startDate, endDate);

                if (dateRange.End.HasValue)
                {
                    // the DateRange picker doesn't automatically add a full day to the end date
                    dateRange.End.Value.AddDays(1);
                }
            }

            var accountGuids  = selectionValues[2].Split(',').Select(a => a.AsGuid()).ToList();
            var accountIdList = new FinancialAccountService((RockContext)serviceInstance.Context).GetByGuids(accountGuids).Select(a => a.Id).ToList();

            int transactionTypeContributionId = Rock.Web.Cache.DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id;

            var financialTransactionsQry = new FinancialTransactionService(rockContext).Queryable()
                                           .Where(xx => xx.TransactionTypeValueId == transactionTypeContributionId);

            if (accountIdList.Any())
            {
                if (accountIdList.Count == 1)
                {
                    int accountId = accountIdList.First();
                    financialTransactionsQry = financialTransactionsQry.Where(xx => xx.TransactionDetails.Any(a => a.AccountId == accountId));
                }
                else
                {
                    financialTransactionsQry = financialTransactionsQry.Where(xx => xx.TransactionDetails.Any(a => accountIdList.Contains(a.AccountId)));
                }
            }

            var firstContributionDateQry = financialTransactionsQry
                                           .GroupBy(xx => xx.AuthorizedPersonAlias.PersonId)
                                           .Select(ss => new
            {
                PersonId = ss.Key,
                FirstTransactionSundayDate = ss.Min(a => a.SundayDate)
            });

            if (dateRange.Start.HasValue)
            {
                firstContributionDateQry = firstContributionDateQry.Where(xx => xx.FirstTransactionSundayDate >= dateRange.Start.Value);
            }

            if (dateRange.End.HasValue)
            {
                firstContributionDateQry = firstContributionDateQry.Where(xx => xx.FirstTransactionSundayDate < dateRange.End.Value);
            }

            var innerQry = firstContributionDateQry.Select(xx => xx.PersonId).AsQueryable();

            var qry = new PersonService(rockContext).Queryable()
                      .Where(p => innerQry.Any(xx => xx == p.Id));

            Expression extractedFilterExpression = FilterExpressionExtractor.Extract <Rock.Model.Person>(qry, parameterExpression, "p");

            return(extractedFilterExpression);
        }
        /// <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 rockContext = (RockContext)serviceInstance.Context;

            string[] selectionValues = selection.Split( '|' );
            if ( selectionValues.Length < 3 )
            {
                return null;
            }

            DateRange dateRange;

            if ( selectionValues.Length >= 4 )
            {
                string slidingDelimitedValues = selectionValues[3].Replace( ',', '|' );
                dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues( slidingDelimitedValues );
            }
            else
            {
                // if converting from a previous version of the selection
                DateTime? startDate = selectionValues[0].AsDateTime();
                DateTime? endDate = selectionValues[1].AsDateTime();
                dateRange = new DateRange( startDate, endDate );

                if ( dateRange.End.HasValue )
                {
                    // the DateRange picker doesn't automatically add a full day to the end date
                    dateRange.End.Value.AddDays( 1 );
                }
            }

            var accountGuids = selectionValues[2].Split( ',' ).Select( a => a.AsGuid() ).ToList();
            var accountIdList = new FinancialAccountService( (RockContext)serviceInstance.Context ).GetByGuids( accountGuids ).Select( a => a.Id ).ToList();

            int transactionTypeContributionId = Rock.Web.Cache.DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() ).Id;

            var financialTransactionsQry = new FinancialTransactionService( rockContext ).Queryable()
                .Where( xx => xx.TransactionTypeValueId == transactionTypeContributionId );

            if ( accountIdList.Any() )
            {
                if ( accountIdList.Count == 1 )
                {
                    int accountId = accountIdList.First();
                    financialTransactionsQry = financialTransactionsQry.Where( xx => xx.TransactionDetails.Any( a => a.AccountId == accountId ) );
                }
                else
                {
                    financialTransactionsQry = financialTransactionsQry.Where( xx => xx.TransactionDetails.Any( a => accountIdList.Contains( a.AccountId ) ) );
                }
            }

            var firstContributionDateQry = financialTransactionsQry
                .GroupBy( xx => xx.AuthorizedPersonAlias.PersonId )
                .Select( ss => new
                {
                    PersonId = ss.Key,
                    FirstTransactionSundayDate = ss.Min( a => a.SundayDate )
                } );

            if ( dateRange.Start.HasValue )
            {
                firstContributionDateQry = firstContributionDateQry.Where( xx => xx.FirstTransactionSundayDate >= dateRange.Start.Value );
            }

            if ( dateRange.End.HasValue )
            {
                firstContributionDateQry = firstContributionDateQry.Where( xx => xx.FirstTransactionSundayDate < dateRange.End.Value );
            }

            var innerQry = firstContributionDateQry.Select( xx => xx.PersonId ).AsQueryable();

            var qry = new PersonService( rockContext ).Queryable()
                .Where( p => innerQry.Any( xx => xx == p.Id ) );

            Expression extractedFilterExpression = FilterExpressionExtractor.Extract<Rock.Model.Person>( qry, parameterExpression, "p" );

            return extractedFilterExpression;
        }