コード例 #1
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entityIdProperty">The entity identifier property.</param>
        /// <param name="selection">The selection.</param>
        /// <returns></returns>
        public override System.Linq.Expressions.Expression GetExpression(Data.RockContext context, System.Linq.Expressions.MemberExpression entityIdProperty, string selection)
        {
            string[] selectionValues = selection.Split('|');
            if (selectionValues.Length < 4)
            {
                return(null);
            }

            ComparisonType comparisonType = selectionValues[0].ConvertToEnum <ComparisonType>(ComparisonType.GreaterThanOrEqualTo);
            decimal        amount         = selectionValues[1].AsDecimalOrNull() ?? 0.00M;

            DateRange dateRange;

            if (selectionValues.Length >= 7)
            {
                string slidingDelimitedValues = selectionValues[6].Replace(',', '|');
                dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(slidingDelimitedValues);
            }
            else
            {
                // if converting from a previous version of the selection
                DateTime?startDate = selectionValues[2].AsDateTime();
                DateTime?endDate   = selectionValues[3].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 accountIdList = new List <int>();

            if (selectionValues.Length >= 5)
            {
                var accountGuids = selectionValues[4].Split(',').Select(a => a.AsGuid()).ToList();
                accountIdList = new FinancialAccountService(context).GetByGuids(accountGuids).Select(a => a.Id).ToList();
            }

            bool combineGiving = false;

            if (selectionValues.Length >= 6)
            {
                combineGiving = selectionValues[5].AsBooleanOrNull() ?? false;
            }

            bool useAnalytics = false;

            if (selectionValues.Length >= 8)
            {
                useAnalytics = selectionValues[7].AsBooleanOrNull() ?? false;
            }

            int transactionTypeContributionId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id;

            IQueryable <decimal> personTotalAmountQry;

            if (useAnalytics)
            {
                var financialTransactionQry = new AnalyticsSourceFinancialTransactionService(context).Queryable()
                                              .Where(xx => xx.TransactionTypeValueId == transactionTypeContributionId)
                                              .Where(xx => xx.AuthorizedPersonAliasId.HasValue);
                if (dateRange.Start.HasValue)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.TransactionDateTime >= dateRange.Start.Value);
                }

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

                bool limitToAccounts = accountIdList.Any();
                if (limitToAccounts)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.AccountId.HasValue && accountIdList.Contains(xx.AccountId.Value));
                }

                if (comparisonType == ComparisonType.LessThan)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Amount < amount);
                }
                else if (comparisonType == ComparisonType.EqualTo)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Amount == amount);
                }
                else if (comparisonType == ComparisonType.GreaterThanOrEqualTo)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Amount >= amount);
                }

                if (combineGiving)
                {
                    var personAmount = new AnalyticsDimPersonCurrentService(context).Queryable()
                                       .Join(financialTransactionQry, p => p.GivingId, f => f.GivingId, (p, f) => new
                    {
                        p.PersonId,
                        f.Amount
                    });

                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p => personAmount
                                                   .Where(ww => ww.PersonId == p.Id)
                                                   .Sum(ww => ww.Amount));
                }
                else
                {
                    var personAmount = new AnalyticsDimPersonCurrentService(context).Queryable()
                                       .Join(financialTransactionQry, p => p.Id, f => f.AuthorizedPersonKey, (p, f) => new
                    {
                        p.PersonId,
                        f.Amount
                    });

                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p => personAmount
                                                   .Where(ww => ww.PersonId == p.Id)
                                                   .Sum(ww => ww.Amount));
                }
            }
            else
            {
                var financialTransactionQry = new FinancialTransactionDetailService(context).Queryable()
                                              .Where(xx => xx.Transaction.TransactionTypeValueId == transactionTypeContributionId)
                                              .Where(xx => xx.Transaction.AuthorizedPersonAliasId.HasValue);

                if (dateRange.Start.HasValue)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Transaction.TransactionDateTime >= dateRange.Start.Value);
                }

                if (dateRange.End.HasValue)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Transaction.TransactionDateTime < dateRange.End.Value);
                }

                bool limitToAccounts = accountIdList.Any();
                if (limitToAccounts)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => accountIdList.Contains(xx.AccountId));
                }

                if (comparisonType == ComparisonType.LessThan)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Amount < amount);
                }
                else if (comparisonType == ComparisonType.EqualTo)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Amount == amount);
                }
                else if (comparisonType == ComparisonType.GreaterThanOrEqualTo)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Amount >= amount);
                }

                if (combineGiving)
                {
                    //// if combineGiving..
                    // if they aren't in a giving group, sum up transactions amounts by the person
                    // if they are in a giving group, sum up transactions amounts by the persons that are in the person's giving group
                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p => financialTransactionQry
                                                   .Where(ww =>
                                                          (!p.GivingGroupId.HasValue && ww.Transaction.AuthorizedPersonAlias.PersonId == p.Id)
                                                          ||
                                                          (p.GivingGroupId.HasValue && ww.Transaction.AuthorizedPersonAlias.Person.GivingGroupId == p.GivingGroupId))
                                                   .Sum(aa => aa.Amount));
                }
                else
                {
                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p => financialTransactionQry
                                                   .Where(ww => ww.Transaction.AuthorizedPersonAlias.PersonId == p.Id)
                                                   .Sum(aa => aa.Amount));
                }
            }

            var selectExpression = SelectExpressionExtractor.Extract(personTotalAmountQry, entityIdProperty, "p");

            return(selectExpression);
        }
コード例 #2
0
        /// <summary>
        /// Gets the expression.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="entityIdProperty">The entity identifier property.</param>
        /// <param name="selection">The selection.</param>
        /// <returns></returns>
        public override System.Linq.Expressions.Expression GetExpression(Data.RockContext context, System.Linq.Expressions.MemberExpression entityIdProperty, string selection)
        {
            string[] selectionValues = selection.Split('|');
            if (selectionValues.Length < 4)
            {
                return(null);
            }

            /* 2020-05-19 MDP
             * The TotalAmount Comparison logic is that the displayed TotalAmount will show blank if the criteria doesn't match
             * For example:
             *   Total Amount >= $100.00
             *   If a person's total giving is $100.01, $100.01 will be displayed as the total giving in the report
             *   If the person's total giving is $99.99, the total giving in the report will just show blank
             *
             *
             *  This display logic is done in the GetGridField method
             */

            DateRange dateRange;

            if (selectionValues.Length >= 7)
            {
                string slidingDelimitedValues = selectionValues[6].Replace(',', '|');
                dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(slidingDelimitedValues);
            }
            else
            {
                // if converting from a previous version of the selection
                DateTime?startDate = selectionValues[2].AsDateTime();
                DateTime?endDate   = selectionValues[3].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 accountIdList = new List <int>();

            if (selectionValues.Length >= 5)
            {
                var accountGuids = selectionValues[4].Split(',').Select(a => a.AsGuid()).Where(a => a != Guid.Empty).ToList();
                accountIdList = new FinancialAccountService(context).GetByGuids(accountGuids).Select(a => a.Id).ToList();
            }

            bool combineGiving = false;

            if (selectionValues.Length >= 6)
            {
                combineGiving = selectionValues[5].AsBooleanOrNull() ?? false;
            }

            bool useAnalytics = false;

            if (selectionValues.Length >= 8)
            {
                useAnalytics = selectionValues[7].AsBooleanOrNull() ?? false;
            }

            int transactionTypeContributionId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id;

            IQueryable <decimal> personTotalAmountQry;

            if (useAnalytics)
            {
                /* 2020-05-20 MDP
                 *  Analytics tables don't have a reference between a transaction and it's refund (unless we join the analytics tables to the TransactionRefund table).
                 *  That isn't a problem unless the refund for a transaction is later than the specified date range.
                 *  We discussed this and decided to not worry abou the late refund problem right now.
                 *
                 *  Also, the total giving will be correct even when factoring in refunds
                 *  because the Analytics tables will have a negative amount for refund transactions
                 *
                 */

                var analyticsFinancialTransactionQry = new AnalyticsSourceFinancialTransactionService(context).Queryable()
                                                       .Where(xx => xx.TransactionTypeValueId == transactionTypeContributionId)
                                                       .Where(xx => xx.AuthorizedPersonAliasId.HasValue);

                if (dateRange.Start.HasValue)
                {
                    analyticsFinancialTransactionQry = analyticsFinancialTransactionQry.Where(xx => xx.TransactionDateTime >= dateRange.Start.Value);
                }

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

                bool limitToAccounts = accountIdList.Any();
                if (limitToAccounts)
                {
                    analyticsFinancialTransactionQry = analyticsFinancialTransactionQry.Where(xx => xx.AccountId.HasValue && accountIdList.Contains(xx.AccountId.Value));
                }

                if (combineGiving)
                {
                    var analyticsPersonAmountQry = new AnalyticsDimPersonCurrentService(context).Queryable()
                                                   .Join(analyticsFinancialTransactionQry, p => p.GivingId, f => f.GivingId, (p, f) => new
                    {
                        p.PersonId,
                        f.Amount
                    });

                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p => analyticsPersonAmountQry
                                                   .Where(ww => ww.PersonId == p.Id)
                                                   .Sum(ww => ww.Amount));
                }
                else
                {
                    var analyticsPersonAmountQry = new AnalyticsDimPersonCurrentService(context).Queryable()
                                                   .Join(analyticsFinancialTransactionQry, p => p.Id, f => f.AuthorizedPersonKey, (p, f) => new
                    {
                        p.PersonId,
                        f.Amount
                    });

                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p => analyticsPersonAmountQry
                                                   .Where(ww => ww.PersonId == p.Id)
                                                   .Sum(ww => ww.Amount));
                }
            }
            else
            {
                var financialTransactionQry = new FinancialTransactionDetailService(context).Queryable()
                                              .Where(xx => xx.Transaction.TransactionTypeValueId == transactionTypeContributionId)
                                              .Where(xx => xx.Transaction.AuthorizedPersonAliasId.HasValue);

                if (dateRange.Start.HasValue)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Transaction.TransactionDateTime >= dateRange.Start.Value);
                }

                if (dateRange.End.HasValue)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => xx.Transaction.TransactionDateTime < dateRange.End.Value);
                }

                bool limitToAccounts = accountIdList.Any();
                if (limitToAccounts)
                {
                    financialTransactionQry = financialTransactionQry.Where(xx => accountIdList.Contains(xx.AccountId));
                }

                // exclude the financial transactions that were used for refunds.
                // This is because we'll get the refund transactions of each non-refund transaction when getting the total amount

                var refundsQry = new FinancialTransactionRefundService(context).Queryable();

                financialTransactionQry = financialTransactionQry.Where(xx => !refundsQry.Any(r => r.Id == xx.TransactionId));

                /* 2020-05-02 MDP
                 * To factor in Refunds, subtract (but actually add since the amount will be negative)
                 * the refund amount if there is a refund associated with that transaction.
                 *
                 * Also, don't apply a date filter on the refund since we want to factor in refunds
                 * that might have occurred after the date range
                 *
                 * The Linq is written in a way to avoid the RefundAmount getting queried twice (once if it is null and another if it not null)
                 */

                if (combineGiving)
                {
                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p =>
                                                   financialTransactionQry.Where(ww => p.GivingId == ww.Transaction.AuthorizedPersonAlias.Person.GivingId
                                                                                 )
                                                   .Select(x => new
                    {
                        x.Amount,
                        RefundAmount = (x.Transaction.RefundDetails.FinancialTransaction
                                        .TransactionDetails
                                        .Where(r => r.AccountId == x.AccountId)
                                        .Sum(r => ( decimal? )r.Amount)
                                        )
                    })
                                                   .Sum
                                                   (
                                                       aa => aa.Amount + (aa.RefundAmount ?? 0.00M)
                                                   )
                                                   );
                }
                else
                {
                    personTotalAmountQry = new PersonService(context).Queryable()
                                           .Select(p =>
                                                   financialTransactionQry.Where(ww => ww.Transaction.AuthorizedPersonAlias.PersonId == p.Id
                                                                                 )
                                                   .Select(x => new
                    {
                        x.Amount,
                        RefundAmount = (x.Transaction.RefundDetails.FinancialTransaction
                                        .TransactionDetails
                                        .Where(r => r.AccountId == x.AccountId)
                                        .Sum(r => ( decimal? )r.Amount)
                                        )
                    })
                                                   .Sum
                                                   (
                                                       aa => aa.Amount + (aa.RefundAmount ?? 0.00M)
                                                   )
                                                   );
                }
            }

            var selectExpression = SelectExpressionExtractor.Extract(personTotalAmountQry, entityIdProperty, "p");

            return(selectExpression);
        }
コード例 #3
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 rockContext = ( RockContext )serviceInstance.Context;

            var selectionConfig = SelectionConfig.Parse(selection) ?? new SelectionConfig();

            ComparisonType comparisonType = selectionConfig.ComparisonType;
            decimal        amount         = selectionConfig.Amount ?? 0.00M;
            DateRange      dateRange      = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(selectionConfig.SlidingDateRangePickerDelimitedValues);

            var        accountGuids = selectionConfig.AccountGuids;
            List <int> accountIdList;

            if (accountGuids != null && accountGuids.Any())
            {
                var financialAccountService = new FinancialAccountService(( RockContext )serviceInstance.Context);
                accountIdList = financialAccountService.GetByGuids(accountGuids).Select(a => a.Id).ToList();
                if (selectionConfig.IncludeChildAccounts)
                {
                    var parentAccountIds = accountIdList.ToList();
                    foreach (var parentAccountId in parentAccountIds)
                    {
                        var descendantChildAccountIds = financialAccountService.GetAllDescendentIds(parentAccountId);
                        accountIdList.AddRange(descendantChildAccountIds);
                    }
                }
            }
            else
            {
                accountIdList = new List <int>();
            }

            bool combineGiving = selectionConfig.CombineGiving;

            int  transactionTypeContributionId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id;
            bool useAnalyticsModels            = selectionConfig.UseAnalyticsModels;

            IQueryable <TransactionDetailData> financialTransactionDetailBaseQry;

            if (useAnalyticsModels)
            {
                financialTransactionDetailBaseQry = new AnalyticsSourceFinancialTransactionService(rockContext).Queryable()
                                                    .Where(xx => xx.AuthorizedPersonAliasId.HasValue)
                                                    .Where(xx => xx.TransactionTypeValueId == transactionTypeContributionId)
                                                    .Select(ss => new TransactionDetailData
                {
                    AuthorizedPersonAliasId = ss.AuthorizedPersonAliasId.Value,
                    TransactionDateTime     = ss.TransactionDateTime,
                    Amount    = ss.Amount,
                    AccountId = ss.AccountId ?? 0
                });
            }
            else
            {
                financialTransactionDetailBaseQry = new FinancialTransactionDetailService(rockContext).Queryable()
                                                    .Where(xx => xx.Transaction.AuthorizedPersonAliasId.HasValue)
                                                    .Where(xx => xx.Transaction.TransactionDateTime.HasValue)
                                                    .Where(xx => xx.Transaction.TransactionTypeValueId == transactionTypeContributionId)
                                                    .Select(ss => new TransactionDetailData
                {
                    AuthorizedPersonAliasId = ss.Transaction.AuthorizedPersonAliasId.Value,
                    TransactionDateTime     = ss.Transaction.TransactionDateTime.Value,
                    Amount    = ss.Amount,
                    AccountId = ss.AccountId
                });
            }

            if (dateRange.Start.HasValue)
            {
                financialTransactionDetailBaseQry = financialTransactionDetailBaseQry.Where(xx => xx.TransactionDateTime >= dateRange.Start.Value);
            }

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

            if (accountIdList.Any())
            {
                if (accountIdList.Count() == 1)
                {
                    var accountId = accountIdList[0];
                    financialTransactionDetailBaseQry = financialTransactionDetailBaseQry.Where(x => accountId == x.AccountId);
                }
                else
                {
                    financialTransactionDetailBaseQry = financialTransactionDetailBaseQry.Where(x => accountIdList.Contains(x.AccountId));
                }
            }

            if (selectionConfig.IgnoreInactiveAccounts)
            {
                var inactiveAccountIdQuery = new FinancialAccountService(rockContext).Queryable().Where(a => !a.IsActive).Select(a => a.Id);
                financialTransactionDetailBaseQry = financialTransactionDetailBaseQry.Where(a => !inactiveAccountIdQuery.Contains(a.AccountId));
            }

            bool excludePersonsWithTransactions = false;

            // Create explicit joins to person alias and person tables so that rendered SQL has an INNER Joins vs OUTER joins on Person and PersonAlias
            var personAliasQry   = new PersonAliasService(rockContext).Queryable();
            var personQryForJoin = new PersonService(rockContext).Queryable(true);
            var financialTransactionDetailAmountQry = financialTransactionDetailBaseQry
                                                      .Join(
                personAliasQry,
                t => t.AuthorizedPersonAliasId,
                pa => pa.Id,
                (t, pa) => new { TransactionDetailData = t, PersonId = pa.PersonId })
                                                      .Join(
                personQryForJoin,
                j1 => j1.PersonId,
                p => p.Id,
                (j1, p) => new { Amount = j1.TransactionDetailData.Amount, Person = p });

            IQueryable <GiverAmountInfo> financialTransactionGivingAmountQry;

            if (combineGiving)
            {
                var financialTransactionGroupByQuery = financialTransactionDetailAmountQry.GroupBy(xx => xx.Person.GivingId);

                financialTransactionGivingAmountQry = financialTransactionGroupByQuery
                                                      .Select(xx => new GiverAmountInfo {
                    GivingId = xx.Key, TotalAmount = xx.Sum(ss => ss.Amount)
                });
            }
            else
            {
                var financialTransactionGroupByQuery = financialTransactionDetailAmountQry.GroupBy(xx => xx.Person.Id);

                financialTransactionGivingAmountQry = financialTransactionGroupByQuery
                                                      .Select(xx => new GiverAmountInfo {
                    PersonId = xx.Key, TotalAmount = xx.Sum(ss => ss.Amount)
                });
            }

            if (comparisonType == ComparisonType.LessThan)
            {
                // NOTE: Since we want people that have less than the specified, but also want to include people to didn't give anything at all (no transactions)
                // make this query the same as the GreaterThan, but use it to EXCLUDE people that gave MORE than the specified amount. That
                // way the filter will include people that had no transactions for the specified date/range and account
                financialTransactionGivingAmountQry = financialTransactionGivingAmountQry.Where(xx => xx.TotalAmount >= amount);
                excludePersonsWithTransactions      = true;
            }
            else if (comparisonType == ComparisonType.EqualTo)
            {
                if (amount == 0.00M)
                {
                    // NOTE: If we want to list people that gave $0.00 (they didn't giving anything)
                    // EXCLUDE people that gave any amount
                    excludePersonsWithTransactions = true;
                }
                else
                {
                    financialTransactionGivingAmountQry = financialTransactionGivingAmountQry.Where(xx => xx.TotalAmount == amount);
                }
            }
            else if (comparisonType == ComparisonType.GreaterThanOrEqualTo)
            {
                // NOTE: if the amount filter is 'they gave $0.00 or more', and doing a GreaterThanOrEqualTo, then we don't need to calculate and compare against TotalAmount
                if (amount == 0.00M)
                {
                    // no need to filter by amount if greater than or equal to $0.00
                }
                else
                {
                    financialTransactionGivingAmountQry = financialTransactionGivingAmountQry.Where(xx => xx.TotalAmount >= amount);
                }
            }

            IQueryable <Model.Person> qry;

            if (combineGiving)
            {
                if (excludePersonsWithTransactions)
                {
                    // the filter is for people that gave LESS than the specified amount, so return people that didn't give MORE than the specified amount
                    qry = new PersonService(rockContext).Queryable().Where(p => !financialTransactionGivingAmountQry.Any(xx => xx.GivingId == p.GivingId));
                }
                else
                {
                    qry = new PersonService(rockContext).Queryable().Where(p => financialTransactionGivingAmountQry.Any(xx => xx.GivingId == p.GivingId));
                }
            }
            else
            {
                if (excludePersonsWithTransactions)
                {
                    // the filter is for people that gave LESS than the specified amount, so return people that didn't give MORE than the specified amount
                    qry = new PersonService(rockContext).Queryable().Where(p => !financialTransactionGivingAmountQry.Any(xx => xx.PersonId == p.Id));
                }
                else
                {
                    qry = new PersonService(rockContext).Queryable().Where(p => financialTransactionGivingAmountQry.Any(xx => xx.PersonId == p.Id));
                }
            }

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

            return(extractedFilterExpression);
        }