Service/Data access class for Rock.Model.FinancialTransactionDetail entity objects.
        /// <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;
            DateTime? startDate = selectionValues[2].AsDateTime();
            DateTime? endDate = selectionValues[3].AsDateTime();
            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;
            }

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

            var financialTransactionQry = new FinancialTransactionDetailService( context ).Queryable()
                .Where( xx => xx.Transaction.TransactionTypeValueId == transactionTypeContributionId )
                .Where( xx => xx.Transaction.AuthorizedPersonAliasId.HasValue );

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

            if ( endDate.HasValue )
            {
                financialTransactionQry = financialTransactionQry.Where( xx => xx.Transaction.TransactionDateTime < endDate.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 );
            }

            IQueryable<decimal> personTotalAmountQry;
            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<Rock.Model.Person>( personTotalAmountQry, entityIdProperty, "p" );

            return selectExpression;
        }
        /// <summary>
        /// Handles the Click event of the lbSave 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 lbSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();

            var txnService = new FinancialTransactionService( rockContext );
            var txnDetailService = new FinancialTransactionDetailService( rockContext );
            var txnImageService = new FinancialTransactionImageService( rockContext );
            var binaryFileService = new BinaryFileService( rockContext );

            FinancialTransaction txn = null;

            int? txnId = hfTransactionId.Value.AsIntegerOrNull();
            int? batchId = hfBatchId.Value.AsIntegerOrNull();

            if ( txnId.HasValue )
            {
                txn = txnService.Get( txnId.Value );
            }

            if ( txn == null )
            {
                txn = new FinancialTransaction();
                txnService.Add( txn );
                txn.BatchId = batchId;
            }

            if ( txn != null )
            {
                if ( ppAuthorizedPerson.PersonId.HasValue )
                {
                    txn.AuthorizedPersonAliasId = ppAuthorizedPerson.PersonAliasId;
                }

                txn.TransactionDateTime = dtTransactionDateTime.SelectedDateTime;
                txn.TransactionTypeValueId = ddlTransactionType.SelectedValue.AsInteger();
                txn.SourceTypeValueId = ddlSourceType.SelectedValueAsInt();

                Guid? gatewayGuid = cpPaymentGateway.SelectedValueAsGuid();
                if ( gatewayGuid.HasValue )
                {
                    var gatewayEntity = EntityTypeCache.Read( gatewayGuid.Value );
                    if ( gatewayEntity != null )
                    {
                        txn.GatewayEntityTypeId = gatewayEntity.Id;
                    }
                    else
                    {
                        txn.GatewayEntityTypeId = null;
                    }
                }
                else
                {
                    txn.GatewayEntityTypeId = null;
                }

                txn.TransactionCode = tbTransactionCode.Text;
                txn.CurrencyTypeValueId = ddlCurrencyType.SelectedValueAsInt();
                txn.CreditCardTypeValueId = ddlCreditCardType.SelectedValueAsInt();
                txn.Summary = tbSummary.Text;

                if ( !Page.IsValid || !txn.IsValid )
                {
                    return;
                }

                foreach ( var txnDetail in TransactionDetailsState )
                {
                    if ( !txnDetail.IsValid )
                    {
                        return;
                    }
                }

                rockContext.WrapTransaction( () =>
                {
                    // Save the transaction
                    rockContext.SaveChanges();

                    // Delete any transaction details that were removed
                    var txnDetailsInDB = txnDetailService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList();
                    var deletedDetails = from txnDetail in txnDetailsInDB
                                         where !TransactionDetailsState.Select( d => d.Guid ).Contains( txnDetail.Guid )
                                         select txnDetail;
                    deletedDetails.ToList().ForEach( txnDetail =>
                    {
                        txnDetailService.Delete( txnDetail );
                    } );
                    rockContext.SaveChanges();

                    // Save Transaction Details
                    foreach ( var editorTxnDetail in TransactionDetailsState )
                    {
                        // Add or Update the activity type
                        var txnDetail = txn.TransactionDetails.FirstOrDefault( d => d.Guid.Equals( editorTxnDetail.Guid ) );
                        if ( txnDetail == null )
                        {
                            txnDetail = new FinancialTransactionDetail();
                            txnDetail.Guid = editorTxnDetail.Guid;
                            txn.TransactionDetails.Add( txnDetail );
                        }
                        txnDetail.AccountId = editorTxnDetail.AccountId;
                        txnDetail.Amount = UseSimpleAccountMode ? tbSingleAccountAmount.Text.AsDecimal() : editorTxnDetail.Amount;
                        txnDetail.Summary = editorTxnDetail.Summary;
                    }
                    rockContext.SaveChanges();

                    // Delete any transaction images that were removed
                    var orphanedBinaryFileIds = new List<int>();
                    var txnImagesInDB = txnImageService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList();
                    foreach ( var txnImage in txnImagesInDB.Where( i => !TransactionImagesState.Contains( i.BinaryFileId ) ) )
                    {
                        orphanedBinaryFileIds.Add( txnImage.BinaryFileId );
                        txnImageService.Delete( txnImage );
                    }

                    // Save Transaction Images
                    int imageOrder = 0;
                    foreach ( var binaryFileId in TransactionImagesState )
                    {
                        // Add or Update the activity type
                        var txnImage = txnImagesInDB.FirstOrDefault( i => i.BinaryFileId == binaryFileId );
                        if ( txnImage == null )
                        {
                            txnImage = new FinancialTransactionImage();
                            txnImage.TransactionId = txn.Id;
                            txn.Images.Add( txnImage );
                        }
                        txnImage.BinaryFileId = binaryFileId;
                        txnImage.Order = imageOrder;
                        imageOrder++;
                    }
                    rockContext.SaveChanges();

                    // Make sure updated binary files are not temporary
                    foreach ( var binaryFile in binaryFileService.Queryable().Where( f => TransactionImagesState.Contains( f.Id ) ) )
                    {
                        binaryFile.IsTemporary = false;
                    }

                    // Delete any orphaned images
                    foreach ( var binaryFile in binaryFileService.Queryable().Where( f => orphanedBinaryFileIds.Contains( f.Id ) ) )
                    {
                        binaryFileService.Delete( binaryFile );
                    }

                    rockContext.SaveChanges();

                } );

                // Save selected options to session state in order to prefill values for next added txn
                Session["NewTxnDefault_BatchId"] = txn.BatchId;
                Session["NewTxnDefault_TransactionDateTime"] = txn.TransactionDateTime;
                Session["NewTxnDefault_TransactionType"] = txn.TransactionTypeValueId;
                Session["NewTxnDefault_SourceType"] = txn.SourceTypeValueId;
                Session["NewTxnDefault_CurrencyType"] = txn.CurrencyTypeValueId;
                Session["NewTxnDefault_CreditCardType"] = txn.CreditCardTypeValueId;
                if ( TransactionDetailsState.Count() == 1 )
                {
                    Session["NewTxnDefault_Account"] = TransactionDetailsState.First().AccountId;
                }
                else
                {
                    Session.Remove("NewTxnDefault_Account");
                }

                // Requery the batch to support EF navigation properties
                var savedTxn = GetTransaction( txn.Id );
                ShowReadOnlyDetails( savedTxn );
            }
        }
예제 #3
0
        private void BuildDynamicControls()
        {
            // Get all the accounts grouped by campus
            if ( _campusAccounts == null )
            {
                using ( var rockContext = new RockContext() )
                {
                    _campusAccounts = new Dictionary<int, Dictionary<int, string>>();

                    Guid contributionGuid = Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid();
                    var contributionAccountIds = new FinancialTransactionDetailService( rockContext )
                        .Queryable().AsNoTracking()
                        .Where( d =>
                            d.Transaction != null &&
                            d.Transaction.TransactionTypeValue != null &&
                            d.Transaction.TransactionTypeValue.Guid.Equals( contributionGuid ) )
                        .Select( d => d.AccountId )
                        .Distinct()
                        .ToList();

                    foreach ( var campusAccounts in new FinancialAccountService( rockContext )
                        .Queryable().AsNoTracking()
                        .Where( a =>
                            a.IsActive &&
                            contributionAccountIds.Contains( a.Id ) )
                        .GroupBy( a => a.CampusId ?? 0 )
                        .Select( c => new
                        {
                            CampusId = c.Key,
                            Accounts = c.OrderBy( a => a.Name ).Select( a => new { a.Id, a.Name } ).ToList()
                        } ) )
                    {
                        _campusAccounts.Add( campusAccounts.CampusId, new Dictionary<int, string>() );
                        foreach ( var account in campusAccounts.Accounts )
                        {
                            _campusAccounts[campusAccounts.CampusId].Add( account.Id, account.Name );
                        }
                    }
                }
            }

            phAccounts.Controls.Clear();

            foreach( var campusId in _campusAccounts )
            {
                var cbList = new RockCheckBoxList();
                cbList.ID = "cblAccounts" + campusId.Key.ToString();

                if ( campusId.Key > 0)
                {
                    var campus = CampusCache.Read( campusId.Key );
                    cbList.Label = campus != null ? campus.Name + " Accounts" : "Campus " + campusId.Key.ToString();
                }
                else
                {
                    cbList.Label = "Accounts";
                }

                cbList.RepeatDirection = RepeatDirection.Vertical;
                cbList.DataValueField = "Key";
                cbList.DataTextField = "Value";
                cbList.DataSource = campusId.Value;
                cbList.DataBind();

                phAccounts.Controls.Add( cbList );
            }
        }
예제 #4
0
        private IEnumerable<Rock.Chart.IChartData> GetChartData()
        {
            var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues( drpSlidingDateRange.DelimitedValues );

            var currenceTypeIds = new List<int>();
            cblCurrencyTypes.SelectedValues.ForEach( i => currenceTypeIds.Add( i.AsInteger() ) );

            var sourceIds = new List<int>();
            cblTransactionSource.SelectedValues.ForEach( i => sourceIds.Add( i.AsInteger() ) );

            var accountIds = new List<int>();
            foreach ( var cblAccounts in phAccounts.Controls.OfType<RockCheckBoxList>() )
            {
                accountIds.AddRange( cblAccounts.SelectedValuesAsInt );
            }

            var chartData = new FinancialTransactionDetailService( _rockContext ).GetChartData(
                hfGroupBy.Value.ConvertToEnumOrNull<ChartGroupBy>() ?? ChartGroupBy.Week,
                hfGraphBy.Value.ConvertToEnumOrNull<TransactionGraphBy>() ?? TransactionGraphBy.Total,
                dateRange.Start,
                dateRange.End,
                nreAmount.LowerValue,
                nreAmount.UpperValue,
                currenceTypeIds,
                sourceIds,
                accountIds,
                dvpDataView.SelectedValueAsInt() );

            return chartData;
        }
예제 #5
0
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            var rockContext = new RockContext();
            var transactionIdsQry = new FinancialTransactionService( rockContext ).Queryable();
            var transactionDetailService = new FinancialTransactionDetailService( rockContext );
            var qry = transactionDetailService.Queryable();

            var targetPerson = this.ContextEntity<Person>();
            if ( targetPerson != null )
            {
                if ( targetPerson.GivingGroupId.HasValue )
                {
                    // gives as part of giving group
                    var groupMemberQry = new GroupMemberService( rockContext ).GetByGroupId( targetPerson.GivingGroupId.Value );
                    qry = qry.Where( a => groupMemberQry.Any( b => b.PersonId == a.Transaction.AuthorizedPersonAlias.PersonId ) );
                }
                else
                {
                    // gives individually
                    qry = qry.Where( a => a.Transaction.AuthorizedPersonAlias.PersonId == targetPerson.Id );
                }
            }

            var qryTransactionsDetailsByYear = qry
                .Where( a => a.Transaction.TransactionDateTime.HasValue )
                .GroupBy( a => SqlFunctions.DatePart( "year", a.Transaction.TransactionDateTime.Value ) );

            var qryAccountSummariesByYear = qryTransactionsDetailsByYear.Select( a => new
            {
                Year = a.Key,
                Accounts = a.GroupBy( b => b.Account ).Select( c => new
                {
                    Account = c.Key,
                    TotalAmount = c.Sum( d => d.Amount )
                } ).OrderBy( e => e.Account.Name )
            } ).OrderByDescending( a => a.Year );

            var summaryList = qryAccountSummariesByYear.ToList();

            var mergeObjects = GlobalAttributesCache.GetMergeFields( this.CurrentPerson );

            var yearsMergeObjects = new List<Dictionary<string, object>>();
            foreach ( var item in summaryList )
            {
                var accountsList = new List<object>();
                foreach ( var a in item.Accounts )
                {
                    var accountDictionary = new Dictionary<string, object>();
                    accountDictionary.Add( "Account", a.Account );
                    accountDictionary.Add( "TotalAmount", a.TotalAmount );
                    accountsList.Add( accountDictionary );
                }

                var yearDictionary = new Dictionary<string, object>();
                yearDictionary.Add( "Year", item.Year );
                yearDictionary.Add( "SummaryRows", accountsList );

                yearsMergeObjects.Add( yearDictionary );
            }

            mergeObjects.Add( "Rows", yearsMergeObjects );

            lLavaOutput.Text = string.Empty;
            if ( GetAttributeValue( "EnableDebug" ).AsBooleanOrNull().GetValueOrDefault( false ) )
            {
                lLavaOutput.Text = mergeObjects.lavaDebugInfo( rockContext );
            }

            string template = GetAttributeValue( "LavaTemplate" );

            lLavaOutput.Text += template.ResolveMergeFields( mergeObjects ).ResolveClientIds( upnlContent.ClientID );
        }
 /// <summary>
 /// Handles the RowSelected event of the gTransactionDetails control.
 /// </summary>
 /// <param name="sender">The source of the event.</param>
 /// <param name="e">The <see cref="Rock.Web.UI.Controls.RowEventArgs"/> instance containing the event data.</param>
 protected void gTransactionDetails_RowSelected( object sender, Rock.Web.UI.Controls.RowEventArgs e )
 {
     if ( !readOnly )
     {
         var rockContext = new RockContext();
         LoadRelatedImages( new FinancialTransactionService( rockContext ).Get( hfIdTransValue.ValueAsInt() ).Id );
         var transactionDetailsId = (int)e.RowKeyValue;
         hfIdValue.Value = transactionDetailsId.ToString();
         var ftd = new FinancialTransactionDetailService( rockContext ).Get( transactionDetailsId );
         ddlTransactionAccount.SelectedValue = ftd.AccountId.ToString();
         tbTransactionAmount.Text = ftd.Amount.ToString();
         tbTransactionSummary.Text = ftd.Summary;
         mdDetails.Show();
     }
 }
예제 #7
0
        /// <summary>
        /// Handles the Click event of the lbSave 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 lbSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();

            var txnService = new FinancialTransactionService( rockContext );
            var txnDetailService = new FinancialTransactionDetailService( rockContext );
            var txnImageService = new FinancialTransactionImageService( rockContext );
            var binaryFileService = new BinaryFileService( rockContext );

            FinancialTransaction txn = null;

            int? txnId = hfTransactionId.Value.AsIntegerOrNull();
            int? batchId = hfBatchId.Value.AsIntegerOrNull();

            var changes = new List<string>();

            if ( txnId.HasValue )
            {
                txn = txnService.Get( txnId.Value );
            }

            if ( txn == null )
            {
                txn = new FinancialTransaction();
                txnService.Add( txn );
                txn.BatchId = batchId;
                changes.Add( "Created transaction" );
            }

            if ( txn != null )
            {
                if ( txn.FinancialPaymentDetail == null )
                {
                    txn.FinancialPaymentDetail = new FinancialPaymentDetail();
                }

                string newPerson = ppAuthorizedPerson.PersonName;

                if ( batchId.HasValue )
                {
                    if ( !txn.AuthorizedPersonAliasId.Equals( ppAuthorizedPerson.PersonAliasId ) )
                    {
                        string prevPerson = ( txn.AuthorizedPersonAlias != null && txn.AuthorizedPersonAlias.Person != null ) ?
                            txn.AuthorizedPersonAlias.Person.FullName : string.Empty;
                        History.EvaluateChange( changes, "Person", prevPerson, newPerson );
                    }

                    History.EvaluateChange( changes, "Date/Time", txn.TransactionDateTime, dtTransactionDateTime.SelectedDateTime );
                    History.EvaluateChange( changes, "Type", GetDefinedValue( txn.TransactionTypeValueId ), GetDefinedValue( ddlTransactionType.SelectedValue.AsInteger() ) );
                    History.EvaluateChange( changes, "Source", GetDefinedValue( txn.SourceTypeValueId ), GetDefinedValue( ddlSourceType.SelectedValueAsInt() ) );

                    if ( !txn.FinancialGatewayId.Equals( gpPaymentGateway.SelectedValueAsInt() ) )
                    {
                        History.EvaluateChange( changes, "Gateway", GetFinancialGatewayName( txn.FinancialGatewayId, rockContext ), GetFinancialGatewayName( gpPaymentGateway.SelectedValueAsInt(), rockContext ) );
                    }

                    History.EvaluateChange( changes, "Transaction Code", txn.TransactionCode, tbTransactionCode.Text );
                    History.EvaluateChange( changes, "Currency Type", GetDefinedValue( txn.FinancialPaymentDetail.CurrencyTypeValueId ), GetDefinedValue( ddlCurrencyType.SelectedValueAsInt() ) );
                    History.EvaluateChange( changes, "Credit Card Type", GetDefinedValue( txn.FinancialPaymentDetail.CreditCardTypeValueId ), GetDefinedValue( ddlCreditCardType.SelectedValueAsInt() ) );
                    History.EvaluateChange( changes, "Summary", txn.Summary, tbSummary.Text );
                    History.EvaluateChange( changes, "Is Refund", ( txn.RefundDetails != null ), cbIsRefund.Checked );
                }

                txn.AuthorizedPersonAliasId = ppAuthorizedPerson.PersonAliasId;
                txn.TransactionDateTime = dtTransactionDateTime.SelectedDateTime;
                txn.TransactionTypeValueId = ddlTransactionType.SelectedValue.AsInteger();
                txn.SourceTypeValueId = ddlSourceType.SelectedValueAsInt();
                txn.FinancialGatewayId = gpPaymentGateway.SelectedValueAsInt();
                txn.TransactionCode = tbTransactionCode.Text;
                txn.FinancialPaymentDetail.CurrencyTypeValueId = ddlCurrencyType.SelectedValueAsInt();
                txn.FinancialPaymentDetail.CreditCardTypeValueId = ddlCreditCardType.SelectedValueAsInt();

                txn.Summary = tbSummary.Text;

                decimal totalAmount = TransactionDetailsState.Select( d => d.Amount ).ToList().Sum();
                if ( cbIsRefund.Checked && totalAmount > 0 )
                {
                    nbErrorMessage.Title = "Incorrect Refund Amount";
                    nbErrorMessage.Text = "<p>A refund should have a negative amount. Please unselect the refund option, or change amounts to be negative values.</p>";
                    nbErrorMessage.Visible = true;
                    return;
                }

                if ( cbIsRefund.Checked )
                {
                    if ( txn.RefundDetails != null )
                    {
                        txn.RefundDetails = new FinancialTransactionRefund();
                    }
                    txn.RefundDetails.RefundReasonValueId = ddlRefundReasonEdit.SelectedValueAsId();
                    txn.RefundDetails.RefundReasonSummary = tbRefundSummaryEdit.Text;
                }

                if ( !Page.IsValid || !txn.IsValid )
                {
                    return;
                }

                foreach ( var txnDetail in TransactionDetailsState )
                {
                    if ( !txnDetail.IsValid )
                    {
                        return;
                    }
                }

                rockContext.WrapTransaction( () =>
                {
                    // Save the transaction
                    rockContext.SaveChanges();

                    // Delete any transaction details that were removed
                    var txnDetailsInDB = txnDetailService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList();
                    var deletedDetails = from txnDetail in txnDetailsInDB
                                         where !TransactionDetailsState.Select( d => d.Guid ).Contains( txnDetail.Guid )
                                         select txnDetail;
                    deletedDetails.ToList().ForEach( txnDetail =>
                    {
                        if ( batchId.HasValue )
                        {
                            History.EvaluateChange( changes, txnDetail.Account != null ? txnDetail.Account.Name : "Unknown", txnDetail.Amount.FormatAsCurrency(), string.Empty );
                        }
                        txnDetailService.Delete( txnDetail );
                    } );

                    // Save Transaction Details
                    foreach ( var editorTxnDetail in TransactionDetailsState )
                    {
                        string oldAccountName = string.Empty;
                        string newAccountName = string.Empty;
                        decimal oldAmount = 0.0M;
                        decimal newAmount = 0.0M;

                        // Add or Update the activity type
                        var txnDetail = txn.TransactionDetails.FirstOrDefault( d => d.Guid.Equals( editorTxnDetail.Guid ) );
                        if ( txnDetail != null )
                        {
                            oldAccountName = AccountName( txnDetail.AccountId );
                            oldAmount = txnDetail.Amount;
                        }
                        else
                        {
                            txnDetail = new FinancialTransactionDetail();
                            txnDetail.Guid = editorTxnDetail.Guid;
                            txn.TransactionDetails.Add( txnDetail );
                        }

                        newAccountName = AccountName( editorTxnDetail.AccountId );
                        newAmount = UseSimpleAccountMode ? tbSingleAccountAmount.Text.AsDecimal() : editorTxnDetail.Amount;

                        if ( batchId.HasValue )
                        {
                            if ( string.IsNullOrWhiteSpace(oldAccountName) )
                            {
                                History.EvaluateChange( changes, newAccountName, string.Empty, newAmount.FormatAsCurrency() );
                            }
                            else
                            {
                                if ( oldAccountName == newAccountName )
                                {
                                    if ( oldAmount != newAmount )
                                    {
                                        History.EvaluateChange( changes, oldAccountName, oldAmount.FormatAsCurrency(), newAmount.FormatAsCurrency() );
                                    }
                                }
                                else
                                {
                                    History.EvaluateChange( changes, oldAccountName, oldAmount.FormatAsCurrency(), string.Empty );
                                    History.EvaluateChange( changes, newAccountName, string.Empty, newAmount.FormatAsCurrency() );
                                }
                            }
                        }

                        txnDetail.AccountId = editorTxnDetail.AccountId;
                        txnDetail.Amount = newAmount;
                        txnDetail.Summary = editorTxnDetail.Summary;

                        if ( editorTxnDetail.AttributeValues != null )
                        {
                            txnDetail.LoadAttributes();
                            txnDetail.AttributeValues = editorTxnDetail.AttributeValues;
                            rockContext.SaveChanges();
                            txnDetail.SaveAttributeValues( rockContext );
                        }
                    }

                    // Delete any transaction images that were removed
                    var orphanedBinaryFileIds = new List<int>();
                    var txnImagesInDB = txnImageService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList();
                    foreach ( var txnImage in txnImagesInDB.Where( i => !TransactionImagesState.Contains( i.BinaryFileId ) ) )
                    {
                        changes.Add( "Removed Image" );
                        orphanedBinaryFileIds.Add( txnImage.BinaryFileId );
                        txnImageService.Delete( txnImage );
                    }

                    // Save Transaction Images
                    int imageOrder = 0;
                    foreach ( var binaryFileId in TransactionImagesState )
                    {
                        // Add or Update the activity type
                        var txnImage = txnImagesInDB.FirstOrDefault( i => i.BinaryFileId == binaryFileId );
                        if ( txnImage == null )
                        {
                            changes.Add( "Added Image" );
                            txnImage = new FinancialTransactionImage();
                            txnImage.TransactionId = txn.Id;
                            txn.Images.Add( txnImage );
                        }
                        else
                        {
                            if ( txnImage.BinaryFileId != binaryFileId )
                            {
                                changes.Add( "Updated Image" );
                            }
                        }

                        txnImage.BinaryFileId = binaryFileId;
                        txnImage.Order = imageOrder;
                        imageOrder++;
                    }

                    rockContext.SaveChanges();

                    // Make sure updated binary files are not temporary
                    foreach ( var binaryFile in binaryFileService.Queryable().Where( f => TransactionImagesState.Contains( f.Id ) ) )
                    {
                        binaryFile.IsTemporary = false;
                    }

                    // Delete any orphaned images
                    foreach ( var binaryFile in binaryFileService.Queryable().Where( f => orphanedBinaryFileIds.Contains( f.Id ) ) )
                    {
                        binaryFileService.Delete( binaryFile );
                    }

                    // Update any attributes
                    txn.LoadAttributes(rockContext);
                    txn.FinancialPaymentDetail.LoadAttributes(rockContext);
                    Helper.GetEditValues(phAttributeEdits, txn);
                    Helper.GetEditValues(phPaymentAttributeEdits, txn.FinancialPaymentDetail);

                    // If the transaction is associated with a batch, update that batch's history
                    if ( batchId.HasValue )
                    {
                        HistoryService.SaveChanges(
                            rockContext,
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                            batchId.Value,
                            changes,
                            !string.IsNullOrWhiteSpace( newPerson ) ? newPerson : string.Format( "Transaction Id:{0}", txn.Id ),
                            typeof( FinancialTransaction ),
                            txn.Id
                        );
                    }

                    rockContext.SaveChanges();
                    txn.SaveAttributeValues(rockContext);
                    txn.FinancialPaymentDetail.SaveAttributeValues(rockContext);
                } );

                // Save selected options to session state in order to prefill values for next added txn
                Session["NewTxnDefault_BatchId"] = txn.BatchId;
                Session["NewTxnDefault_TransactionDateTime"] = txn.TransactionDateTime;
                Session["NewTxnDefault_TransactionType"] = txn.TransactionTypeValueId;
                Session["NewTxnDefault_SourceType"] = txn.SourceTypeValueId;
                Session["NewTxnDefault_CurrencyType"] = txn.FinancialPaymentDetail.CurrencyTypeValueId;
                Session["NewTxnDefault_CreditCardType"] = txn.FinancialPaymentDetail.CreditCardTypeValueId;
                if ( TransactionDetailsState.Count() == 1 )
                {
                    Session["NewTxnDefault_Account"] = TransactionDetailsState.First().AccountId;
                }
                else
                {
                    Session.Remove("NewTxnDefault_Account");
                }

                // Requery the batch to support EF navigation properties
                var savedTxn = GetTransaction( txn.Id );
                if ( savedTxn != null )
                {
                    savedTxn.LoadAttributes();
                    savedTxn.FinancialPaymentDetail.LoadAttributes();
                    ShowReadOnlyDetails( savedTxn );
                }
            }
        }
        /// <summary>
        /// Handles the Click event of the btnNext 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 btnNext_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();
            var financialTransactionService = new FinancialTransactionService( rockContext );
            var financialTransactionDetailService = new FinancialTransactionDetailService( rockContext );
            var financialPersonBankAccountService = new FinancialPersonBankAccountService( rockContext );
            int txnId = hfTransactionId.Value.AsInteger();
            var financialTransaction = financialTransactionService
                    .Queryable( "AuthorizedPersonAlias.Person,ProcessedByPersonAlias.Person" )
                    .FirstOrDefault( t => t.Id == txnId );

            // set the AuthorizedPersonId (the person who wrote the check, for example) to the if the SelectNew person (if selected) or person selected in the drop down (if there is somebody selected)
            int? authorizedPersonId = ppSelectNew.PersonId ?? ddlIndividual.SelectedValue.AsIntegerOrNull();

            var accountNumberSecured = hfCheckMicrHashed.Value;

            if ( cbTotalAmount.Text.AsDecimalOrNull().HasValue && !authorizedPersonId.HasValue )
            {
                nbSaveError.Text = "Transaction must be matched to a person when the amount is specified.";
                nbSaveError.Visible = true;
                return;
            }

            // if the transaction was previously matched, but user unmatched it, save it as an unmatched transaction and clear out the detail records (we don't want an unmatched transaction to have detail records)
            if ( financialTransaction != null &&
                financialTransaction.AuthorizedPersonAliasId.HasValue &&
                !authorizedPersonId.HasValue )
            {
                financialTransaction.AuthorizedPersonAliasId = null;
                foreach ( var detail in financialTransaction.TransactionDetails )
                {
                    financialTransactionDetailService.Delete( detail );
                }

                rockContext.SaveChanges();

                // if the transaction was unmatched, clear out the ProcessedBy fields since we didn't match the transaction and are moving on to process another transaction
                MarkTransactionAsNotProcessedByCurrentUser( hfTransactionId.Value.AsInteger() );
            }

            // if the transaction is matched to somebody, attempt to save it.  Otherwise, if the transaction was previously matched, but user unmatched it, save it as an unmatched transaction
            if ( financialTransaction != null && authorizedPersonId.HasValue )
            {
                bool requiresMicr = financialTransaction.CurrencyTypeValue.Guid == Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK.AsGuid();
                if ( requiresMicr && string.IsNullOrWhiteSpace( accountNumberSecured ) )
                {
                    // should be showing already, but just in case
                    nbNoMicrWarning.Visible = true;
                    return;
                }

                if ( cbTotalAmount.Text.AsDecimalOrNull() == null )
                {
                    nbSaveError.Text = "Total amount must be allocated to accounts.";
                    nbSaveError.Visible = true;
                    return;
                }

                int? personAliasId = new PersonAliasService( rockContext ).GetPrimaryAliasId( authorizedPersonId.Value );

                // if this transaction has an accountnumber associated with it (in other words, it's a scanned check), ensure there is a financialPersonBankAccount record
                if ( !string.IsNullOrWhiteSpace( accountNumberSecured ) )
                {
                    var financialPersonBankAccount = financialPersonBankAccountService.Queryable().Where( a => a.AccountNumberSecured == accountNumberSecured && a.PersonAlias.PersonId == authorizedPersonId.Value ).FirstOrDefault();
                    if ( financialPersonBankAccount == null )
                    {
                        if ( personAliasId.HasValue )
                        {
                            financialPersonBankAccount = new FinancialPersonBankAccount();
                            financialPersonBankAccount.PersonAliasId = personAliasId.Value;
                            financialPersonBankAccount.AccountNumberSecured = accountNumberSecured;

                            var checkMicrClearText = Encryption.DecryptString( financialTransaction.CheckMicrEncrypted );
                            var parts = checkMicrClearText.Split( '_' );
                            if ( parts.Length >= 2 )
                            {
                                financialPersonBankAccount.AccountNumberMasked = parts[1].Masked();
                            }

                            financialPersonBankAccountService.Add( financialPersonBankAccount );
                        }
                    }
                }

                if ( personAliasId.HasValue )
                {
                    financialTransaction.AuthorizedPersonAliasId = personAliasId;
                }

                // just in case this transaction is getting re-edited either by the same user, or somebody else, clean out any existing TransactionDetail records
                foreach ( var detail in financialTransaction.TransactionDetails.ToList() )
                {
                    financialTransactionDetailService.Delete( detail );
                }

                foreach ( var accountBox in rptAccounts.ControlsOfTypeRecursive<CurrencyBox>() )
                {
                    var amount = accountBox.Text.AsDecimalOrNull();

                    if ( amount.HasValue && amount.Value >= 0 )
                    {
                        var financialTransactionDetail = new FinancialTransactionDetail();
                        financialTransactionDetail.TransactionId = financialTransaction.Id;
                        financialTransactionDetail.AccountId = accountBox.Attributes["data-account-id"].AsInteger();
                        financialTransactionDetail.Amount = amount.Value;
                        financialTransactionDetailService.Add( financialTransactionDetail );
                    }
                }

                financialTransaction.ProcessedByPersonAliasId = this.CurrentPersonAlias.Id;
                financialTransaction.ProcessedDateTime = RockDateTime.Now;

                rockContext.SaveChanges();
            }
            else
            {
                // if the transaction was not matched, clear out the ProcessedBy fields since we didn't match the transaction and are moving on to process another transaction
                MarkTransactionAsNotProcessedByCurrentUser( hfTransactionId.Value.AsInteger() );
            }

            NavigateToTransaction( Direction.Next );
        }
예제 #9
0
        /// <summary>
        /// Binds the chart attendance grid.
        /// </summary>
        private void BindChartAmountGrid()
        {
            var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues( drpSlidingDateRange.DelimitedValues );

            var currenceTypeIds = new List<int>();
            cblCurrencyTypes.SelectedValues.ForEach( i => currenceTypeIds.Add( i.AsInteger() ) );

            var sourceIds = new List<int>();
            cblTransactionSource.SelectedValues.ForEach( i => sourceIds.Add( i.AsInteger() ) );

            var accountIds = new List<int>();
            foreach ( var cblAccounts in phAccounts.Controls.OfType<RockCheckBoxList>() )
            {
                accountIds.AddRange( cblAccounts.SelectedValuesAsInt );
            }

            SortProperty sortProperty = gChartAmount.SortProperty;

            var chartData = new FinancialTransactionDetailService( _rockContext ).GetChartData(
                hfGroupBy.Value.ConvertToEnumOrNull<ChartGroupBy>() ?? ChartGroupBy.Week,
                hfGraphBy.Value.ConvertToEnumOrNull<TransactionGraphBy>() ?? TransactionGraphBy.Total,
                dateRange.Start,
                dateRange.End,
                nreAmount.LowerValue,
                nreAmount.UpperValue,
                currenceTypeIds,
                sourceIds,
                accountIds,
                dvpDataView.SelectedValueAsInt() );

            if ( sortProperty != null )
            {
                gChartAmount.DataSource = chartData.AsQueryable().Sort( sortProperty ).ToList();
            }
            else
            {
                gChartAmount.DataSource = chartData.OrderBy( c => c.DateTimeStamp ).ToList();
            }

            gChartAmount.DataBind();
        }
예제 #10
0
        /// <summary>
        /// Shows the refund dialog.
        /// </summary>
        private void ShowRefundDialog()
        {
            int? txnId = hfTransactionId.Value.AsIntegerOrNull();
            if ( txnId.HasValue )
            {
                using ( var rockContext = new RockContext() )
                {
                    var txnService = new FinancialTransactionService( rockContext );
                    var txn = txnService.Get( txnId.Value );
                    if ( txn != null )
                    {
                        var totalAmount = txn.TotalAmount;
                        var otherAmounts = new FinancialTransactionDetailService( rockContext )
                            .Queryable().AsNoTracking()
                            .Where( d =>
                                d.Transaction != null &&
                                (
                                    (
                                        txn.TransactionCode != null &&
                                        txn.TransactionCode != "" &&
                                        d.Transaction.TransactionCode == txn.TransactionCode &&
                                        d.TransactionId != txn.Id ) ||
                                    (
                                        d.Transaction.RefundDetails != null &&
                                        d.Transaction.RefundDetails.OriginalTransactionId == txn.Id
                                    )
                                )
                            )
                            .Select( d => d.Amount )
                            .ToList()
                            .Sum();

                        totalAmount += otherAmounts;

                        tbRefundAmount.Text = ( totalAmount > 0.0m ? totalAmount : 0.0m ).ToString( "N2" );
                        ddlRefundReason.SelectedIndex = -1;
                        tbRefundSummary.Text = string.Empty;

                        bool hasGateway = !string.IsNullOrWhiteSpace( txn.TransactionCode ) && txn.FinancialGateway != null;
                        cbProcess.Visible = hasGateway;
                        cbProcess.Checked = hasGateway;

                        ShowDialog( "REFUND" );
                        _focusControl = tbRefundAmount;
                    }
                }
            }
        }
        /// <summary>
        /// Binds the grid.
        /// </summary>
        private void BindGrid()
        {
            var contributionType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() );
            if ( contributionType != null )
            {
                var rockContext = new RockContext();
                var transactionDetailService = new FinancialTransactionDetailService( rockContext );
                var qry = transactionDetailService.Queryable().AsNoTracking()
                    .Where( a =>
                        a.Transaction.TransactionTypeValueId == contributionType.Id &&
                        a.Transaction.TransactionDateTime.HasValue );

                var targetPerson = this.ContextEntity<Person>();
                if ( targetPerson != null )
                {
                    qry = qry.Where( t => t.Transaction.AuthorizedPersonAlias.Person.GivingId == targetPerson.GivingId );
                }

                List<SummaryRecord> summaryList;

                using ( new Rock.Data.QueryHintScope( rockContext, QueryHintType.RECOMPILE ) )
                {
                    summaryList = qry
                        .GroupBy( a => new { a.Transaction.TransactionDateTime.Value.Year, a.AccountId } )
                        .Select( t => new SummaryRecord
                        {
                            Year = t.Key.Year,
                            AccountId = t.Key.AccountId,
                            TotalAmount = t.Sum( d => d.Amount )
                        } ).OrderByDescending( a => a.Year )
                        .ToList();
                }

                var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields( this.RockPage, this.CurrentPerson );
                var financialAccounts = new FinancialAccountService( rockContext ).Queryable().Select( a => new { a.Id, a.Name } ).ToDictionary( k => k.Id, v => v.Name );

                var yearsMergeObjects = new List<Dictionary<string, object>>();
                foreach ( var item in summaryList.GroupBy( a => a.Year ) )
                {
                    var year = item.Key;
                    var accountsList = new List<object>();
                    foreach ( var a in item )
                    {
                        var accountDictionary = new Dictionary<string, object>();
                        accountDictionary.Add( "Account", financialAccounts.ContainsKey( a.AccountId ) ? financialAccounts[a.AccountId] : string.Empty );
                        accountDictionary.Add( "TotalAmount", a.TotalAmount );
                        accountsList.Add( accountDictionary );
                    }

                    var yearDictionary = new Dictionary<string, object>();
                    yearDictionary.Add( "Year", year );
                    yearDictionary.Add( "SummaryRows", accountsList );

                    yearsMergeObjects.Add( yearDictionary );
                }

                mergeFields.Add( "Rows", yearsMergeObjects );

                lLavaOutput.Text = string.Empty;
                if ( GetAttributeValue( "EnableDebug" ).AsBoolean() && IsUserAuthorized( Authorization.EDIT ) )
                {
                    lLavaOutput.Text = mergeFields.lavaDebugInfo( rockContext );
                }

                string template = GetAttributeValue( "LavaTemplate" );

                lLavaOutput.Text += template.ResolveMergeFields( mergeFields ).ResolveClientIds( upnlContent.ClientID );
            }
        }
        /// <summary>
        /// Handles the SaveClick event of the mdDetails control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void mdDetails_SaveClick( object sender, EventArgs e )
        {
            var rockContext = new RockContext();
            if ( !string.IsNullOrWhiteSpace( tbTransactionAmount.Text ) )
            {
                var ftdService = new FinancialTransactionDetailService( rockContext );
                FinancialTransactionDetail ftd = null;
                var transactionDetailId = int.Parse( hfIdValue.Value );
                if ( transactionDetailId > 0 )
                {
                    ftd = ftdService.Get( transactionDetailId );
                }
                else
                {
                    ftd = new FinancialTransactionDetail { Id = 0 };
                }

                ftd.TransactionId = hfIdTransValue.ValueAsInt();
                ftd.AccountId = int.Parse( ddlTransactionAccount.SelectedValue );
                ftd.Amount = decimal.Parse( tbTransactionAmount.Text );
                ftd.Summary = tbTransactionSummary.Text;

                if ( transactionDetailId == 0 )
                {
                    ftdService.Add( ftd );
                }

                rockContext.SaveChanges();
            }

            mdDetails.Hide();
            FinancialTransaction transaction = new FinancialTransaction();
            transaction = new FinancialTransactionService( rockContext ).Get( hfIdTransValue.ValueAsInt() );
            BindTransactionDetailGrid( transaction );
            LoadRelatedImages( transaction.Id );
        }
 /// <summary>
 /// Binds the transaction detail grid.
 /// </summary>
 /// <param name="transaction">The transaction.</param>
 private void BindTransactionDetailGrid( FinancialTransaction transaction )
 {
     // Load the TransactionDetails grid here if this transaction already exists.
     if ( transaction.Id != 0 )
     {
         var financialTransactionDetails = new FinancialTransactionDetailService( new RockContext() ).Queryable().Where( trans => trans.TransactionId == transaction.Id ).ToList();
         gTransactionDetails.DataSource = financialTransactionDetails;
         gTransactionDetails.DataBind();
         pnlTransactionDetails.Visible = true;
     }
     else
     {
         pnlTransactionDetails.Visible = false;
     }
 }
        private void DisplayResults()
        {
            RockContext rockContext = new RockContext();

            var statementYear = RockDateTime.Now.Year;

            if ( Request["StatementYear"] != null )
            {
                Int32.TryParse( Request["StatementYear"].ToString(), out statementYear );
            }

            FinancialTransactionDetailService financialTransactionDetailService = new FinancialTransactionDetailService( rockContext );

            var qry = financialTransactionDetailService.Queryable().AsNoTracking()
                        .Where( t=> t.Transaction.AuthorizedPersonAlias.Person.GivingId == CurrentPerson.GivingId);

            qry = qry.Where( t => t.Transaction.TransactionDateTime.Value.Year == statementYear );

            if ( string.IsNullOrWhiteSpace( GetAttributeValue( "Accounts" ) ) )
            {
                qry = qry.Where( t => t.Account.IsTaxDeductible );
            } else
            {
                var accountGuids = GetAttributeValue( "Accounts" ).Split( ',' ).Select( Guid.Parse ).ToList();
                qry = qry.Where( t => accountGuids.Contains( t.Account.Guid ) );
            }

            qry = qry.OrderByDescending( t => t.Transaction.TransactionDateTime );

            var mergeFields = new Dictionary<string, object>();
            mergeFields.Add( "StatementStartDate", "1/1/" + statementYear.ToString() );
            if ( statementYear == RockDateTime.Now.Year )
            {
                mergeFields.Add( "StatementEndDate", RockDateTime.Now );
            }
            else
            {
                mergeFields.Add( "StatementEndDate", "12/31/" + statementYear.ToString() );
            }

            var familyGroupTypeId = GroupTypeCache.Read( Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY ).Id;
            var groupMemberQry = new GroupMemberService( rockContext ).Queryable().Where( m => m.Group.GroupTypeId == familyGroupTypeId );

            // get giving group members in order by family role (adult -> child) and then gender (male -> female)
            var givingGroup = new PersonService( rockContext ).Queryable().AsNoTracking()
                                    .Where( p => p.GivingId == CurrentPerson.GivingId )
                                    .GroupJoin(
                                        groupMemberQry,
                                        p => p.Id,
                                        m => m.PersonId,
                                        (p, m) => new {p, m})
                                    .SelectMany( x => x.m.DefaultIfEmpty(), (y,z) => new { Person = y.p, GroupMember = z} )
                                    .Select( p => new { FirstName = p.Person.NickName, LastName = p.Person.LastName, FamilyRoleOrder = p.GroupMember.GroupRole.Order, Gender = p.Person.Gender, PersonId = p.Person.Id } )
                                    .DistinctBy(p => p.PersonId)
                                    .OrderBy(p => p.FamilyRoleOrder).ThenBy(p => p.Gender)
                                    .ToList();

            // make a list of person ids in the giving group
            List<int> givingGroupIdsOnly = new List<int>();
            foreach ( var x in givingGroup )
            {
                givingGroupIdsOnly.Add(x.PersonId);
            }

            string salutation = string.Empty;

            if (givingGroup.GroupBy(g => g.LastName).Count() == 1 )
            {
                salutation = string.Join( ", ", givingGroup.Select( g => g.FirstName ) ) + " " + givingGroup.FirstOrDefault().LastName;
                if ( salutation.Contains( "," ) )
                {
                    salutation = salutation.ReplaceLastOccurrence( ",", " &" );
                }
            }
            else
            {
                salutation = string.Join( ", ", givingGroup.Select( g => g.FirstName + " " + g.LastName ) );
                if ( salutation.Contains( "," ) )
                {
                    salutation = salutation.ReplaceLastOccurrence( ",", " &" );
                }
            }
            mergeFields.Add( "Salutation", salutation );

            var homeAddress = CurrentPerson.GetHomeLocation();
            if ( homeAddress != null )
            {
                mergeFields.Add( "StreetAddress1", homeAddress.Street1 );
                mergeFields.Add( "StreetAddress2", homeAddress.Street2 );
                mergeFields.Add( "City", homeAddress.City );
                mergeFields.Add( "State", homeAddress.State );
                mergeFields.Add( "PostalCode", homeAddress.PostalCode );
                mergeFields.Add( "Country", homeAddress.Country );
            }
            else
            {
                mergeFields.Add( "StreetAddress1", string.Empty );
                mergeFields.Add( "StreetAddress2", string.Empty );
                mergeFields.Add( "City", string.Empty );
                mergeFields.Add( "State", string.Empty );
                mergeFields.Add( "PostalCode", string.Empty );
                mergeFields.Add( "Country", string.Empty );
            }

            mergeFields.Add( "TransactionDetails", qry.ToList() );

            mergeFields.Add( "AccountSummary", qry.GroupBy( t => t.Account.Name ).Select( s => new AccountSummary { AccountName = s.Key, Total = s.Sum( a => a.Amount ), Order = s.Max(a => a.Account.Order) } ).OrderBy(s => s.Order ));

            // pledge information
            var pledges = new FinancialPledgeService( rockContext ).Queryable().AsNoTracking()
                                .Where(p =>
                                    p.PersonAlias.Person.GivingId == CurrentPerson.GivingId
                                    && (p.StartDate.Year == statementYear || p.EndDate.Year == statementYear))
                                .GroupBy(p => p.Account)
                                .Select(g => new PledgeSummary {
                                                    AccountId = g.Key.Id,
                                                    AccountName = g.Key.Name,
                                                    AmountPledged = g.Sum( p => p.TotalAmount ),
                                                    PledgeStartDate = g.Min(p => p.StartDate),
                                                    PledgeEndDate = g.Max( p => p.EndDate)
                                } )
                                .ToList();

            // add detailed pledge information
            foreach(var pledge in pledges )
            {
                var adjustedPedgeEndDate = pledge.PledgeEndDate.Value.Date.AddHours( 23 ).AddMinutes( 59 ).AddSeconds( 59 );
                pledge.AmountGiven = new FinancialTransactionDetailService( rockContext ).Queryable()
                                            .Where( t =>
                                                 t.AccountId == pledge.AccountId
                                                 && givingGroupIdsOnly.Contains(t.Transaction.AuthorizedPersonAlias.PersonId)
                                                 && t.Transaction.TransactionDateTime >= pledge.PledgeStartDate
                                                 && t.Transaction.TransactionDateTime <= adjustedPedgeEndDate )
                                            .Sum( t => t.Amount );

                pledge.AmountRemaining = (pledge.AmountGiven > pledge.AmountPledged) ? 0 : (pledge.AmountPledged - pledge.AmountGiven);

                if ( pledge.AmountPledged > 0 )
                {
                    var test = (double)pledge.AmountGiven / (double)pledge.AmountPledged;
                    pledge.PercentComplete = (int)((pledge.AmountGiven * 100) / pledge.AmountPledged);
                }
            }

            mergeFields.Add( "Pledges", pledges );

            var template = GetAttributeValue( "LavaTemplate" );

            lResults.Text = template.ResolveMergeFields( mergeFields );

            // show debug info
            if ( GetAttributeValue( "EnableDebug" ).AsBoolean() && IsUserAuthorized( Authorization.EDIT ) )
            {
                lDebug.Visible = true;
                lDebug.Text = mergeFields.lavaDebugInfo();
            }
        }
예제 #15
0
        /// <summary>
        /// Binds the attendees grid.
        /// </summary>
        private void BindGiversGrid()
        {
            // Get all the selected criteria values
            var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues( drpSlidingDateRange.DelimitedValues );
            var start = dateRange.Start;
            var end = dateRange.End;

            var minAmount = nreAmount.LowerValue;
            var maxAmount = nreAmount.UpperValue;

            var currencyTypeIds = new List<int>();
            cblCurrencyTypes.SelectedValues.ForEach( i => currencyTypeIds.Add( i.AsInteger() ) );

            var sourceIds = new List<int>();
            cblTransactionSource.SelectedValues.ForEach( i => sourceIds.Add( i.AsInteger() ) );

            var accountIds = new List<int>();
            foreach ( var cblAccounts in phAccounts.Controls.OfType<RockCheckBoxList>() )
            {
                accountIds.AddRange( cblAccounts.SelectedValuesAsInt );
            }

            var groupBy = hfGroupBy.Value.ConvertToEnumOrNull<ChartGroupBy>() ?? ChartGroupBy.Week;
            var graphBy = hfGraphBy.Value.ConvertToEnumOrNull<TransactionGraphBy>() ?? TransactionGraphBy.Total;

            GiversViewBy viewBy = GiversViewBy.Giver;
            if ( !HideViewByOption )
            {
                viewBy = hfViewBy.Value.ConvertToEnumOrNull<GiversViewBy>() ?? GiversViewBy.Giver;
            }

            // Collection of async queries to run before assembling data
            var qryTasks = new List<Task>();

            // Get all person summary data
            var personInfoList = new List<PersonInfo>();
            qryTasks.Add( Task.Run( () =>
            {
                var dt = FinancialTransactionDetailService.GetGivingAnalyticsPersonSummary(
                    start, end, minAmount, maxAmount, accountIds, currencyTypeIds, sourceIds )
                    .Tables[0];

                foreach ( DataRow row in dt.Rows )
                {
                    var personInfo = new PersonInfo();

                    if ( !DBNull.Value.Equals( row["Id"] ) )
                    {
                        personInfo.Id = (int)row["Id"];
                    }

                    if ( !DBNull.Value.Equals( row["Guid"] ) )
                    {
                        personInfo.Guid = row["Guid"].ToString().AsGuid();
                    }

                    if ( !DBNull.Value.Equals( row["NickName"] ) )
                    {
                        personInfo.NickName = row["NickName"].ToString();
                    }

                    if ( !DBNull.Value.Equals( row["LastName"] ) )
                    {
                        personInfo.LastName = row["LastName"].ToString();
                    }

                    if ( !DBNull.Value.Equals( row["Email"] ) )
                    {
                        personInfo.Email = row["Email"].ToString();
                    }

                    if ( !DBNull.Value.Equals( row["GivingId"] ) )
                    {
                        personInfo.GivingId = row["GivingId"].ToString();
                    }

                    if ( !DBNull.Value.Equals( row["FirstGift"] ) )
                    {
                        personInfo.FirstGift = row["FirstGift"].ToString().AsDateTime();
                    }

                    if ( !DBNull.Value.Equals( row["LastGift"] ) )
                    {
                        personInfo.LastGift = row["LastGift"].ToString().AsDateTime();
                    }

                    if ( !DBNull.Value.Equals( row["NumberGifts"] ) )
                    {
                        personInfo.NumberGifts = (int)row["NumberGifts"];
                    }

                    if ( !DBNull.Value.Equals( row["TotalAmount"] ) )
                    {
                        personInfo.TotalAmount = (decimal)row["TotalAmount"];
                    }

                    if ( !DBNull.Value.Equals( row["IsGivingLeader"] ) )
                    {
                        personInfo.IsGivingLeader = (bool)row["IsGivingLeader"];
                    }

                    if ( !DBNull.Value.Equals( row["IsAdult"] ) )
                    {
                        personInfo.IsAdult = (bool)row["IsAdult"];
                    }

                    if ( !DBNull.Value.Equals( row["IsChild"] ) )
                    {
                        personInfo.IsChild = (bool)row["IsChild"];
                    }

                    personInfo.AccountAmounts = new Dictionary<int, decimal>();

                    personInfoList.Add( personInfo );
                }

            } ) );

            // Get the account summary values
            DataTable dtAccountSummary = null;
            qryTasks.Add( Task.Run( () =>
            {
                dtAccountSummary = FinancialTransactionDetailService.GetGivingAnalyticsAccountTotals(
                    start, end, accountIds, currencyTypeIds, sourceIds )
                    .Tables[0];
            } ) );

            // Get the first/last ever dates
            var firstEverVals = new Dictionary<string, DateTime>();
            var lastEverVals = new Dictionary<string, DateTime>();
            qryTasks.Add( Task.Run( () =>
            {
                var dt = FinancialTransactionDetailService.GetGivingAnalyticsFirstLastEverDates()
                    .Tables[0];
                foreach ( DataRow row in dt.Rows )
                {
                    if ( !DBNull.Value.Equals( row["GivingId"] ) )
                    {
                        if ( !DBNull.Value.Equals( row["FirstEverGift"] ) )
                        {
                            firstEverVals.Add( row["GivingId"].ToString(), row["FirstEverGift"].ToString().AsDateTime().Value );
                        }
                        if ( !DBNull.Value.Equals( row["LastEverGift"] ) )
                        {
                            lastEverVals.Add( row["GivingId"].ToString(), row["LastEverGift"].ToString().AsDateTime().Value );
                        }
                    }
                }

            } ) );

            // If a dataview filter was included, find the people who match that criteria
            List<int> dataViewPersonIds = null;
            var dataViewId = dvpDataView.SelectedValueAsInt();
            if ( dataViewId.HasValue )
            {
                qryTasks.Add( Task.Run( () =>
                {
                    dataViewPersonIds = new List<int>();
                    var dataView = new DataViewService( _rockContext ).Get( dataViewId.Value );
                    if ( dataView != null )
                    {
                        var errorMessages = new List<string>();
                        var dvPersonService = new PersonService( _rockContext );
                        ParameterExpression paramExpression = dvPersonService.ParameterExpression;
                        Expression whereExpression = dataView.GetExpression( dvPersonService, paramExpression, out errorMessages );

                        SortProperty sort = null;
                        var dataViewPersonIdQry = dvPersonService
                            .Queryable().AsNoTracking()
                            .Where( paramExpression, whereExpression, sort )
                            .Select( p => p.Id );
                        dataViewPersonIds = dataViewPersonIdQry.ToList();
                    }
                } ) );
            }

            qryTasks.Add( Task.Run( () =>
            {
                // Clear all the existing grid columns
                var selectField = new SelectField();
                var oldSelectField = gGiversGifts.ColumnsOfType<SelectField>().FirstOrDefault();
                if ( oldSelectField != null )
                {
                    selectField.SelectedKeys.AddRange( oldSelectField.SelectedKeys );
                }

                gGiversGifts.Columns.Clear();

                // Add a column for selecting rows
                gGiversGifts.Columns.Add( selectField );

                // Add a hidden column for person id
                gGiversGifts.Columns.Add(
                    new RockBoundField
                    {
                        DataField = "Id",
                        HeaderText = "Person Id",
                        SortExpression = "Id",
                        Visible = false,
                        ExcelExportBehavior = ExcelExportBehavior.AlwaysInclude
                    } );

                // Add a column for the person's name
                gGiversGifts.Columns.Add(
                    new RockBoundField
                    {
                        DataField = "PersonName",
                        HeaderText = "Person",
                        SortExpression = "LastName,NickName"
                    } );

                // add a column for email (but is only included on excel export)
                gGiversGifts.Columns.Add(
                    new RockBoundField
                    {
                        DataField = "Email",
                        HeaderText = "Email",
                        SortExpression = "Email",
                        Visible = false,
                        ExcelExportBehavior = ExcelExportBehavior.AlwaysInclude
                    } );

                // Add a column for total amount
                gGiversGifts.Columns.Add(
                    new CurrencyField
                    {
                        DataField = "TotalAmount",
                        HeaderText = "Total",
                        SortExpression = "TotalAmount"
                    } );

                // Add columns for the selected account totals
                if ( accountIds.Any() )
                {
                    var accounts = new FinancialAccountService( _rockContext )
                        .Queryable().AsNoTracking()
                        .Where( a => accountIds.Contains( a.Id ) )
                        .ToList();

                    foreach ( int accountId in accountIds )
                    {
                        var account = accounts.FirstOrDefault( a => a.Id == accountId );
                        if ( account != null )
                        {
                            gGiversGifts.Columns.Add(
                                new GivingAnalyticsAccountField
                                {
                                    DataField = string.Format( "Account_{0}", account.Id ),
                                    HeaderText = account.Name,
                                    SortExpression = string.Format( "Account:{0}", account.Id ),
                                } );
                        }
                    }
                }

                // Add a column for the number of gifts
                var numberGiftsField = new RockBoundField
                {
                    DataField = "NumberGifts",
                    HeaderText = "Number of Gifts",
                    SortExpression = "NumberGifts",
                    DataFormatString = "{0:N0}",
                };
                numberGiftsField.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
                gGiversGifts.Columns.Add( numberGiftsField );

                if ( !radFirstTime.Checked )
                {
                    // Add a column to indicate if this is a first time giver
                    gGiversGifts.Columns.Add(
                        new BoolField
                        {
                            DataField = "IsFirstEverGift",
                            HeaderText = "Is First Gift",
                            SortExpression = "IsFirstEverGift"
                        } );

                    // Add a column for the first gift date ( that matches criteria )
                    gGiversGifts.Columns.Add(
                        new DateField
                        {
                            DataField = "FirstGift",
                            HeaderText = "First Gift in Period",
                            SortExpression = "FirstGift"
                        } );
                }

                // Add a column for the first-ever gift date ( to any tax-deductible account )
                gGiversGifts.Columns.Add(
                    new DateField
                    {
                        DataField = "FirstEverGift",
                        HeaderText = "First Gift Ever",
                        SortExpression = "FirstEverGift"
                    } );

                // Add a column for the first gift date ( that matches criteria )
                gGiversGifts.Columns.Add(
                    new DateField
                    {
                        DataField = "LastGift",
                        HeaderText = "Last Gift in Period",
                        SortExpression = "LastGift"
                    } );

                // Add a column for the last-ever gift date ( to any tax-deductible account )
                gGiversGifts.Columns.Add(
                    new DateField
                    {
                        DataField = "LastEverGift",
                        HeaderText = "Last Gift Ever",
                        SortExpression = "LastEverGift"
                    } );

            } ) );

            // Wait for all the queries to finish
            Task.WaitAll( qryTasks.ToArray() );

            // If dataview was selected and it's being used to filter results people, not in dataview
            if ( dataViewId.HasValue && rblDataViewAction.SelectedValue != "All" && dataViewPersonIds.Any() )
            {
                personInfoList = personInfoList.Where( c => dataViewPersonIds.Contains( c.Id ) ).ToList();
            }

            // if dataview was selected and it includes people not in the result set,
            if ( dataViewId.HasValue && rblDataViewAction.SelectedValue == "All" && dataViewPersonIds.Any() )
            {
                // Query for the names of each of these people
                foreach ( var person in new PersonService( _rockContext )
                    .Queryable().AsNoTracking()
                    .Where( p => dataViewPersonIds.Contains( p.Id ) )
                    .Select( p => new
                    {
                        p.Id,
                        p.GivingId,
                        p.GivingLeaderId,
                        p.Guid,
                        p.NickName,
                        p.LastName,
                        p.Email
                    } ) )
                {
                    // Check for a first ever gift date
                    var firstEverGiftDate = firstEverVals
                        .Where( f => f.Key == person.GivingId )
                        .Select( f => f.Value )
                        .FirstOrDefault();

                    // Check for a last ever gift date
                    var lastEverGiftDate = lastEverVals
                        .Where( f => f.Key == person.GivingId )
                        .Select( f => f.Value )
                        .FirstOrDefault();

                    var personInfo = new PersonInfo();
                    personInfo.Id = person.Id;
                    personInfo.Guid = person.Guid;
                    personInfo.NickName = person.NickName;
                    personInfo.LastName = person.LastName;
                    personInfo.Email = person.Email;
                    personInfo.GivingId = person.GivingId;
                    personInfo.IsGivingLeader = person.Id == person.GivingLeaderId;
                    personInfo.FirstEverGift = firstEverGiftDate;
                    personInfo.LastEverGift = lastEverGiftDate;

                    personInfoList.Add( personInfo );
                }
            }

            // Filter out recs that don't match the view by
            switch ( viewBy )
            {
                case GiversViewBy.Giver:
                    {
                        personInfoList = personInfoList.Where( p => p.IsGivingLeader ).ToList();
                        break;
                    }
                case GiversViewBy.Adults:
                    {
                        personInfoList = personInfoList.Where( p => p.IsAdult ).ToList();
                        break;
                    }
                case GiversViewBy.Children:
                    {
                        personInfoList = personInfoList.Where( p => p.IsChild ).ToList();
                        break;
                    }
            }

            // Add the first/last gift dates
            foreach ( var personInfo in personInfoList )
            {
                if ( firstEverVals.ContainsKey( personInfo.GivingId ) )
                {
                    personInfo.FirstEverGift = firstEverVals[personInfo.GivingId];
                }
                if ( lastEverVals.ContainsKey( personInfo.GivingId ) )
                {
                    personInfo.LastEverGift = lastEverVals[personInfo.GivingId];
                }
            }

            // Check to see if we're only showing first time givers
            if ( radFirstTime.Checked )
            {
                personInfoList = personInfoList
                    .Where( p => p.IsFirstEverGift )
                    .ToList();
            }

            // Check to see if grid should display only people who gave a certain number of times and if so
            // set the min value
            if ( radByPattern.Checked )
            {
                int minCount = tbPatternXTimes.Text.AsInteger();
                var previousGivingIds = new List<string>();

                if ( cbPatternAndMissed.Checked )
                {
                    var missedStart = drpPatternDateRange.LowerValue;
                    var missedEnd = drpPatternDateRange.UpperValue;
                    if ( missedStart.HasValue && missedEnd.HasValue )
                    {
                        // Get the givingleaderids that gave any amount during the pattern's date range. These
                        // are needed so that we know who to exclude from the result set
                        previousGivingIds = new FinancialTransactionDetailService( _rockContext )
                            .Queryable().AsNoTracking()
                            .Where( d =>
                                d.Transaction.TransactionDateTime.HasValue &&
                                d.Transaction.TransactionDateTime.Value >= missedStart.Value &&
                                d.Transaction.TransactionDateTime.Value < missedEnd.Value &&
                                ( accountIds.Any() && accountIds.Contains( d.AccountId ) || d.Account.IsTaxDeductible ) &&
                                d.Amount != 0.0M )
                            .Select( d => d.Transaction.AuthorizedPersonAlias.Person.GivingId )
                            .ToList();
                    }
                }

                personInfoList = personInfoList
                    .Where( p =>
                        !previousGivingIds.Contains( p.GivingId ) &&
                        p.NumberGifts >= minCount )
                    .ToList();
            }

            // Add account summary info
            foreach ( DataRow row in dtAccountSummary.Rows )
            {
                if ( !DBNull.Value.Equals( row["GivingId"] ) &&
                    !DBNull.Value.Equals( row["AccountId"] ) &&
                    !DBNull.Value.Equals( row["Amount"] ) )
                {
                    string givingId = row["GivingId"].ToString();
                    int accountId = (int)row["AccountId"];
                    decimal amount = (decimal)row["Amount"];

                    foreach ( var personInfo in personInfoList.Where( p => p.GivingId == givingId ) )
                    {
                        personInfo.AccountAmounts.AddOrIgnore( accountId, amount );
                    }
                }
            }

            // Calculate Total
            if ( viewBy == GiversViewBy.Giver )
            {
                pnlTotal.Visible = true;
                decimal amountTotal = personInfoList.Sum( p => p.TotalAmount );
                lTotal.Text = amountTotal.FormatAsCurrency();
            }
            else
            {
                pnlTotal.Visible = false;
            }

            var qry = personInfoList.AsQueryable();

            if ( gGiversGifts.SortProperty != null )
            {
                if ( gGiversGifts.SortProperty.Property.StartsWith( "Account" ) )
                {
                    int? accountId = gGiversGifts.SortProperty.Property.Substring( 8 ).AsIntegerOrNull();
                    if ( accountId.HasValue )
                    {
                        foreach ( var personInfo in personInfoList )
                        {
                            personInfo.SortAmount = personInfo.AccountAmounts.ContainsKey( accountId.Value ) ?
                                personInfo.AccountAmounts[accountId.Value] : 0.0M;
                            if ( gGiversGifts.SortProperty.Direction == SortDirection.Ascending )
                            {
                                gGiversGifts.DataSource = personInfoList.OrderBy( p => p.SortAmount ).ToList();
                            }
                            else
                            {
                                gGiversGifts.DataSource = personInfoList.OrderByDescending( p => p.SortAmount ).ToList();
                            }
                        }
                    }
                    else
                    {
                        gGiversGifts.DataSource = qry.OrderBy( p => p.LastName ).ThenBy( p => p.NickName ).ToList();
                    }
                }
                else
                {
                    gGiversGifts.DataSource = qry.Sort( gGiversGifts.SortProperty ).ToList();
                }
            }
            else
            {
                gGiversGifts.DataSource = qry.OrderBy( p => p.LastName ).ThenBy( p => p.NickName ).ToList();
            }

            gGiversGifts.DataBind();
        }
예제 #16
0
        /// <summary>
        /// Handles the Click event of the lbSave 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 lbSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();

            var txnService = new FinancialTransactionService( rockContext );
            var txnDetailService = new FinancialTransactionDetailService( rockContext );
            var txnImageService = new FinancialTransactionImageService( rockContext );
            var binaryFileService = new BinaryFileService( rockContext );

            FinancialTransaction txn = null;

            int? txnId = hfTransactionId.Value.AsIntegerOrNull();
            int? batchId = hfBatchId.Value.AsIntegerOrNull();

            if ( txnId.HasValue )
            {
                txn = txnService.Get( txnId.Value );
            }

            if ( txn == null && batchId.HasValue )
            {
                txn = new FinancialTransaction();
                txnService.Add( txn );
                txn.BatchId = batchId.Value;
            }

            if ( txn != null )
            {
                txn.AuthorizedPersonId = ppAuthorizedPerson.PersonId;
                txn.TransactionDateTime = dtTransactionDateTime.SelectedDateTime;
                txn.TransactionTypeValueId = ddlTransactionType.SelectedValue.AsInteger();
                txn.SourceTypeValueId = ddlSourceType.SelectedValueAsInt();

                Guid? gatewayGuid = cpPaymentGateway.SelectedValueAsGuid();
                if ( gatewayGuid.HasValue )
                {
                    var gatewayEntity = EntityTypeCache.Read( gatewayGuid.Value );
                    if ( gatewayEntity != null )
                    {
                        txn.GatewayEntityTypeId = gatewayEntity.Id;
                    }
                    else
                    {
                        txn.GatewayEntityTypeId = null;
                    }
                }
                else
                {
                    txn.GatewayEntityTypeId = null;
                }

                txn.TransactionCode = tbTransactionCode.Text;
                txn.CurrencyTypeValueId = ddlCurrencyType.SelectedValueAsInt();
                txn.CreditCardTypeValueId = ddlCreditCardType.SelectedValueAsInt();
                txn.Summary = tbSummary.Text;

                if ( !Page.IsValid || !txn.IsValid )
                {
                    return;
                }

                foreach ( var txnDetail in TransactionDetailsState )
                {
                    if ( !txnDetail.IsValid )
                    {
                        return;
                    }
                }

                foreach ( var txnImage in TransactionImagesState )
                {
                    if ( !txnImage.IsValid )
                    {
                        return;
                    }
                }

                rockContext.WrapTransaction( () =>
                {
                    // Save the transaction
                    rockContext.SaveChanges();

                    // Delete any transaction details that were removed
                    var txnDetailsInDB = txnDetailService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList();
                    var deletedDetails = from txnDetail in txnDetailsInDB
                                         where !TransactionDetailsState.Select( d => d.Guid ).Contains( txnDetail.Guid )
                                         select txnDetail;
                    deletedDetails.ToList().ForEach( txnDetail =>
                    {
                        txnDetailService.Delete( txnDetail );
                    } );
                    rockContext.SaveChanges();

                    // Save Transaction Details
                    foreach ( var editorTxnDetail in TransactionDetailsState )
                    {
                        // Add or Update the activity type
                        var txnDetail = txn.TransactionDetails.FirstOrDefault( d => d.Guid.Equals( editorTxnDetail.Guid ) );
                        if ( txnDetail == null )
                        {
                            txnDetail = new FinancialTransactionDetail();
                            txnDetail.Guid = editorTxnDetail.Guid;
                            txn.TransactionDetails.Add( txnDetail );
                        }
                        txnDetail.AccountId = editorTxnDetail.AccountId;
                        txnDetail.Amount = editorTxnDetail.Amount;
                        txnDetail.Summary = editorTxnDetail.Summary;
                    }
                    rockContext.SaveChanges();

                    // Remove any images that do not have a binary file
                    foreach ( var txnImage in TransactionImagesState.Where( i => i.BinaryFileId == 0 ).ToList() )
                    {
                        TransactionImagesState.Remove( txnImage );
                    }

                    // Delete any transaction images that were removed
                    var txnImagesInDB = txnImageService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList();
                    var deletedImages = from txnImage in txnImagesInDB
                                        where !TransactionImagesState.Select( d => d.Guid ).Contains( txnImage.Guid )
                                        select txnImage;
                    deletedImages.ToList().ForEach( txnImage =>
                    {
                        txnImageService.Delete( txnImage );
                    } );
                    rockContext.SaveChanges();

                    // Save Transaction Images
                    foreach ( var editorTxnImage in TransactionImagesState )
                    {
                        // Add or Update the activity type
                        var txnImage = txn.Images.FirstOrDefault( d => d.Guid.Equals( editorTxnImage.Guid ) );
                        if ( txnImage == null )
                        {
                            txnImage = new FinancialTransactionImage();
                            txnImage.Guid = editorTxnImage.Guid;
                            txn.Images.Add( txnImage );
                        }
                        txnImage.BinaryFileId = editorTxnImage.BinaryFileId;
                        txnImage.TransactionImageTypeValueId = editorTxnImage.TransactionImageTypeValueId;
                    }
                    rockContext.SaveChanges();

                    // Make sure updated binary files are not temporary
                    var savedBinaryFileIds = txn.Images.Select( i => i.BinaryFileId ).ToList();
                    foreach ( var binaryFile in binaryFileService.Queryable().Where( f => savedBinaryFileIds.Contains( f.Id ) ) )
                    {
                        binaryFile.IsTemporary = false;
                    }

                    // Delete any orphaned images
                    var orphanedBinaryFileIds = BinaryFileIds.Where( f => !savedBinaryFileIds.Contains( f ) );
                    foreach ( var binaryFile in binaryFileService.Queryable().Where( f => orphanedBinaryFileIds.Contains( f.Id ) ) )
                    {
                        binaryFileService.Delete( binaryFile );
                    }

                    rockContext.SaveChanges();

                } );

                // Requery the batch to support EF navigation properties
                var savedTxn = GetTransaction( txn.Id );
                ShowReadOnlyDetails( savedTxn );
            }
        }
        private void DisplayResults()
        {
            var numberOfYears = GetAttributeValue( "MaxYearsToDisplay" ).AsInteger();

            RockContext rockContext = new RockContext();

            FinancialTransactionDetailService financialTransactionDetailService = new FinancialTransactionDetailService( rockContext );

            var qry = financialTransactionDetailService.Queryable().AsNoTracking()
                        .Where( t=> t.Transaction.AuthorizedPersonAlias.Person.GivingId == TargetPerson.GivingId);

            if ( string.IsNullOrWhiteSpace( GetAttributeValue( "Accounts" ) ) )
            {
                qry = qry.Where( t => t.Account.IsTaxDeductible );
            } else
            {
                var accountGuids = GetAttributeValue( "Accounts" ).Split( ',' ).Select( Guid.Parse ).ToList();
                qry = qry.Where( t => accountGuids.Contains( t.Account.Guid ) );
            }

            var yearQry = qry.GroupBy( t => t.Transaction.TransactionDateTime.Value.Year )
                                .Select( g => new { Year = g.Key } )
                                .OrderByDescending(y => y.Year);

            var mergeFields = new Dictionary<string, object>();
            mergeFields.Add( "DetailPage", LinkedPageRoute( "DetailPage" ) );
            mergeFields.Add( "StatementYears", yearQry.Take( numberOfYears ) );
            mergeFields.Add( "PersonGuid", TargetPerson.Guid );

            var template = GetAttributeValue( "LavaTemplate" );

            lResults.Text = template.ResolveMergeFields( mergeFields );

            // show debug info
            if ( GetAttributeValue( "EnableDebug" ).AsBoolean() && IsUserAuthorized( Authorization.EDIT ) )
            {
                lDebug.Visible = true;
                lDebug.Text = mergeFields.lavaDebugInfo();
            }
        }
예제 #18
0
        /// <summary>
        /// Handles the Click event of the btnNext 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 btnNext_Click( object sender, EventArgs e )
        {
            var changes = new List<string>();

            var rockContext = new RockContext();
            var financialTransactionService = new FinancialTransactionService( rockContext );
            var financialTransactionDetailService = new FinancialTransactionDetailService( rockContext );
            var financialPersonBankAccountService = new FinancialPersonBankAccountService( rockContext );
            int txnId = hfTransactionId.Value.AsInteger();
            var financialTransaction = financialTransactionService
                    .Queryable( "AuthorizedPersonAlias.Person,ProcessedByPersonAlias.Person" )
                    .FirstOrDefault( t => t.Id == txnId );

            // set the AuthorizedPersonId (the person who wrote the check, for example) to the if the SelectNew person (if selected) or person selected in the drop down (if there is somebody selected)
            int? authorizedPersonId = ppSelectNew.PersonId ?? ddlIndividual.SelectedValue.AsIntegerOrNull();

            var accountNumberSecured = hfCheckMicrHashed.Value;

            if ( cbTotalAmount.Text.AsDecimalOrNull().HasValue && !authorizedPersonId.HasValue )
            {
                nbSaveError.Text = "Transaction must be matched to a person when the amount is specified.";
                nbSaveError.Visible = true;
                return;
            }

            // if the transaction was previously matched, but user unmatched it, save it as an unmatched transaction and clear out the detail records (we don't want an unmatched transaction to have detail records)
            if ( financialTransaction != null &&
                financialTransaction.AuthorizedPersonAliasId.HasValue &&
                !authorizedPersonId.HasValue )
            {
                financialTransaction.AuthorizedPersonAliasId = null;
                foreach ( var detail in financialTransaction.TransactionDetails )
                {
                    History.EvaluateChange( changes, detail.Account != null ? detail.Account.Name : "Unknown", detail.Amount.ToString( "C2" ), string.Empty );
                    financialTransactionDetailService.Delete( detail );
                }

                changes.Add( "Unmatched transaction" );

                HistoryService.SaveChanges(
                    rockContext,
                    typeof( FinancialBatch ),
                    Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                    financialTransaction.BatchId.Value,
                    changes,
                    string.Format( "Transaction Id: {0}", financialTransaction.Id ),
                    typeof( FinancialTransaction ),
                    financialTransaction.Id,
                    false
                );

                rockContext.SaveChanges();

                // if the transaction was unmatched, clear out the ProcessedBy fields since we didn't match the transaction and are moving on to process another transaction
                MarkTransactionAsNotProcessedByCurrentUser( hfTransactionId.Value.AsInteger() );
            }

            // if the transaction is matched to somebody, attempt to save it.  Otherwise, if the transaction was previously matched, but user unmatched it, save it as an unmatched transaction
            if ( financialTransaction != null && authorizedPersonId.HasValue )
            {
                bool requiresMicr =
                    financialTransaction.FinancialPaymentDetail != null &&
                    financialTransaction.FinancialPaymentDetail.CurrencyTypeValue != null &&
                    financialTransaction.FinancialPaymentDetail.CurrencyTypeValue.Guid == Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK.AsGuid();

                if ( cbTotalAmount.Text.AsDecimalOrNull() == null )
                {
                    nbSaveError.Text = "Total amount must be allocated to accounts.";
                    nbSaveError.Visible = true;
                    return;
                }

                var personAlias = new PersonAliasService( rockContext ).GetPrimaryAlias( authorizedPersonId.Value );
                int? personAliasId = personAlias != null ? personAlias.Id : (int?)null;

                // if this transaction has an accountnumber associated with it (in other words, it's a valid scanned check), ensure there is a financialPersonBankAccount record
                if ( financialTransaction.MICRStatus == MICRStatus.Success && !string.IsNullOrWhiteSpace( accountNumberSecured ) )
                {
                    var financialPersonBankAccount = financialPersonBankAccountService.Queryable().Where( a => a.AccountNumberSecured == accountNumberSecured && a.PersonAlias.PersonId == authorizedPersonId.Value ).FirstOrDefault();
                    if ( financialPersonBankAccount == null )
                    {
                        if ( personAliasId.HasValue )
                        {
                            financialPersonBankAccount = new FinancialPersonBankAccount();
                            financialPersonBankAccount.PersonAliasId = personAliasId.Value;
                            financialPersonBankAccount.AccountNumberSecured = accountNumberSecured;

                            var checkMicrClearText = Encryption.DecryptString( financialTransaction.CheckMicrParts );
                            var parts = checkMicrClearText.Split( '_' );
                            if ( parts.Length >= 2 )
                            {
                                financialPersonBankAccount.AccountNumberMasked = parts[1].Masked();
                            }

                            financialPersonBankAccountService.Add( financialPersonBankAccount );
                        }
                    }
                }

                string prevPerson = ( financialTransaction.AuthorizedPersonAlias != null && financialTransaction.AuthorizedPersonAlias.Person != null ) ?
                    financialTransaction.AuthorizedPersonAlias.Person.FullName : string.Empty;
                string newPerson = string.Empty;
                if ( personAliasId.HasValue )
                {
                    newPerson = personAlias.Person.FullName;
                    financialTransaction.AuthorizedPersonAliasId = personAliasId;
                }

                History.EvaluateChange( changes, "Person", prevPerson, newPerson );

                // just in case this transaction is getting re-edited either by the same user, or somebody else, clean out any existing TransactionDetail records
                foreach ( var detail in financialTransaction.TransactionDetails.ToList() )
                {
                    financialTransactionDetailService.Delete( detail );
                    History.EvaluateChange( changes, detail.Account != null ? detail.Account.Name : "Unknown", detail.Amount.ToString( "C2" ), string.Empty );
                }

                foreach ( var accountBox in rptAccounts.ControlsOfTypeRecursive<CurrencyBox>() )
                {
                    var amount = accountBox.Text.AsDecimalOrNull();

                    if ( amount.HasValue && amount.Value >= 0 )
                    {
                        var financialTransactionDetail = new FinancialTransactionDetail();
                        financialTransactionDetail.TransactionId = financialTransaction.Id;
                        financialTransactionDetail.AccountId = accountBox.Attributes["data-account-id"].AsInteger();
                        financialTransactionDetail.Amount = amount.Value;
                        financialTransactionDetailService.Add( financialTransactionDetail );

                        History.EvaluateChange( changes, accountBox.Label, 0.0M.ToString( "C2" ), amount.Value.ToString( "C2" ) );

                    }
                }

                financialTransaction.ProcessedByPersonAliasId = this.CurrentPersonAlias.Id;
                financialTransaction.ProcessedDateTime = RockDateTime.Now;

                changes.Add( "Matched transaction" );

                HistoryService.SaveChanges(
                    rockContext,
                    typeof( FinancialBatch ),
                    Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                    financialTransaction.BatchId.Value,
                    changes,
                    personAlias != null && personAlias.Person != null ? personAlias.Person.FullName : string.Format( "Transaction Id: {0}", financialTransaction.Id ),
                    typeof( FinancialTransaction ),
                    financialTransaction.Id,
                    false
                );

                rockContext.SaveChanges();
            }
            else
            {
                // if the transaction was not matched, clear out the ProcessedBy fields since we didn't match the transaction and are moving on to process another transaction
                MarkTransactionAsNotProcessedByCurrentUser( hfTransactionId.Value.AsInteger() );
            }

            NavigateToTransaction( Direction.Next );
        }
예제 #19
0
        /// <summary>
        /// Binds the attendees grid.
        /// </summary>
        private void BindGiversGrid()
        {
            // Get all the selected criteria values
            var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues( drpSlidingDateRange.DelimitedValues );
            var start = dateRange.Start;
            var end = dateRange.End;

            var minAmount = nreAmount.LowerValue;
            var maxAmount = nreAmount.UpperValue;

            var currencyTypeIds = new List<int>();
            cblCurrencyTypes.SelectedValues.ForEach( i => currencyTypeIds.Add( i.AsInteger() ) );

            var sourceTypeIds = new List<int>();
            cblTransactionSource.SelectedValues.ForEach( i => sourceTypeIds.Add( i.AsInteger() ) );

            var accountIds = new List<int>();
            foreach ( var cblAccounts in phAccounts.Controls.OfType<RockCheckBoxList>() )
            {
                accountIds.AddRange( cblAccounts.SelectedValuesAsInt );
            }

            var dataViewId = dvpDataView.SelectedValueAsInt();

            GiversViewBy viewBy = GiversViewBy.Giver;
            if ( !HideViewByOption )
            {
                viewBy = hfViewBy.Value.ConvertToEnumOrNull<GiversViewBy>() ?? GiversViewBy.Giver;
            }

            // Clear all the existing grid columns
            var selectField = new SelectField();
            var oldSelectField = gGiversGifts.ColumnsOfType<SelectField>().FirstOrDefault();
            if (oldSelectField != null )
            {
                selectField.SelectedKeys.AddRange( oldSelectField.SelectedKeys );
            }

            gGiversGifts.Columns.Clear();

            // Add a column for selecting rows
            gGiversGifts.Columns.Add( selectField );

            // Add a column for the person's name
            gGiversGifts.Columns.Add(
                new RockBoundField
                {
                    DataField = "PersonName",
                    HeaderText = "Person",
                    SortExpression = "LastName,NickName"
                } );

            // add a column for email (but is only included on excel export)
            gGiversGifts.Columns.Add(
                new RockBoundField
                {
                    DataField = "Email",
                    HeaderText = "Email",
                    SortExpression = "Email",
                    Visible = false,
                    ExcelExportBehavior = ExcelExportBehavior.AlwaysInclude
                } );

            // Add a column for total amount
            gGiversGifts.Columns.Add(
                new CurrencyField
                {
                    DataField = "TotalAmount",
                    HeaderText = "Total",
                    SortExpression = "TotalAmount"
                } );

            // Add columns for the selected account totals
            if ( accountIds.Any() )
            {
                var accounts = new FinancialAccountService( _rockContext )
                    .Queryable().AsNoTracking()
                    .Where( a => accountIds.Contains( a.Id ) )
                    .ToList();

                foreach ( int accountId in accountIds )
                {
                    var account = accounts.FirstOrDefault( a => a.Id == accountId );
                    if ( account != null )
                    {
                        gGiversGifts.Columns.Add(
                            new CurrencyField
                            {
                                DataField = account.Id.ToString(),
                                HeaderText = account.Name,
                                SortExpression = account.Id.ToString()
                            } );
                    }
                }
            }

            // Add a column for the number of gifts
            var numberGiftsField = new RockBoundField
                {
                    DataField = "NumberGifts",
                    HeaderText = "Number of Gifts",
                    SortExpression = "NumberGifts",
                    DataFormatString = "{0:N0}",
                };
            numberGiftsField.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
            gGiversGifts.Columns.Add( numberGiftsField );

            // Add a column to indicate if this is a first time giver
            gGiversGifts.Columns.Add(
                new BoolField
                {
                    DataField = "IsFirstEverGift",
                    HeaderText = "Is First Gift",
                    SortExpression = "IsFirstEverGift"
                } );

            // Add a column for the first gift date ( that matches criteria )
            gGiversGifts.Columns.Add(
                new DateField
                {
                    DataField = "FirstGift",
                    HeaderText = "First Gift",
                    SortExpression = "FirstGift"
                } );

            // Add a column for the first-ever gift date ( to any tax-deductible account )
            gGiversGifts.Columns.Add(
                new DateField
                {
                    DataField = "FirstEverGift",
                    HeaderText = "First Gift Ever",
                    SortExpression = "FirstEverGift"
                } );

            var transactionDetailService = new FinancialTransactionDetailService( _rockContext );
            var personService = new PersonService( _rockContext );

            // If dataview was selected get the person id's returned by the dataview
            var dataViewPersonIds = new List<int>();
            if ( dataViewId.HasValue )
            {
                var dataView = new DataViewService( _rockContext ).Get( dataViewId.Value );
                if ( dataView != null )
                {
                    var errorMessages = new List<string>();
                    ParameterExpression paramExpression = personService.ParameterExpression;
                    Expression whereExpression = dataView.GetExpression( personService, paramExpression, out errorMessages );

                    SortProperty sortProperty = null;
                    var dataViewPersonIdQry = personService
                        .Queryable().AsNoTracking()
                        .Where( paramExpression, whereExpression, sortProperty )
                        .Select( p => p.Id );
                    dataViewPersonIds = dataViewPersonIdQry.ToList();
                }
            }

            // Check to see if grid should display only people who gave a certain number of times and if so
            // set the min value
            int minCount = 0;
            var previousPersonIds = new List<int>();
            if ( radByPattern.Checked )
            {
                minCount = tbPatternXTimes.Text.AsInteger();
                var missedStart = drpPatternDateRange.LowerValue;
                var missedEnd = drpPatternDateRange.UpperValue;
                if ( missedStart.HasValue && missedEnd.HasValue )
                {
                    // Get the givingids that gave any amount during the pattern's date range. These
                    // are needed so that we know who to exclude from the result set
                    var previousGivingIds = transactionDetailService
                        .Queryable().AsNoTracking()
                        .Where( d =>
                            d.Transaction.TransactionDateTime.HasValue &&
                            d.Transaction.TransactionDateTime.Value >= missedStart.Value &&
                            d.Transaction.TransactionDateTime.Value < missedEnd.Value &&
                            accountIds.Contains( d.AccountId ) &&
                            d.Amount != 0.0M )
                        .Select( d => d.Transaction.AuthorizedPersonAlias.Person.GivingId );

                    // Now get the person ids from the givingids
                    previousPersonIds = personService
                        .Queryable().AsNoTracking()
                        .Where( p => previousGivingIds.Contains( p.GivingId ) )
                        .Select( p => p.Id )
                        .ToList();
                }
            }

            // Call the stored procedure to get all the giving data that matches the selected criteria.
            // The stored procedure returns two tables. First is a list of all matching transaction summary
            // information and the second table is each giving leader's first-ever gift date to a tax-deductible account
            DataSet ds = FinancialTransactionDetailService.GetGivingAnalytics( start, end, minAmount, maxAmount,
                accountIds, currencyTypeIds, sourceTypeIds,  dataViewId, viewBy );

            // Get the results table
            DataTable dtResults = ds.Tables[0];

            // Get the first-ever gift dates and load them into a dictionary for faster matching
            DataTable dtFirstEver = ds.Tables[1];
            var firstEverVals = new Dictionary<int, DateTime>();
            foreach( DataRow row in ds.Tables[1].Rows )
            {
                if ( !DBNull.Value.Equals( row["FirstEverGift"] ) )
                {
                    firstEverVals.Add( (int)row["PersonId"], (DateTime)row["FirstEverGift"] );
                }
            }

            // Add columns to the result set for the first-ever data
            dtResults.Columns.Add( new DataColumn( "IsFirstEverGift", typeof( bool ) ) );
            dtResults.Columns.Add( new DataColumn( "FirstEverGift", typeof( DateTime ) ) );

            foreach( DataRow row in dtResults.Rows )
            {
                bool rowValid = true;

                // Get the person id
                int personId = (int)row["Id"];

                if ( radByPattern.Checked )
                {
                    // If pattern was specified check minimum gifts and other date range
                    int numberGifts = (int)row["NumberGifts"];
                    if ( numberGifts < minCount )
                    {
                        rowValid = false;
                    }
                    else
                    {
                        // If this giving leader gave during the pattern date, remove the row since we
                        // only want those who did not
                        if ( previousPersonIds.Contains( personId ) )
                        {
                            rowValid = false;
                        }
                    }
                }

                if ( dataViewId.HasValue )
                {
                    // If a dataview filter was specified, and this row is not part of dataview,
                    // remove it
                    if ( !dataViewPersonIds.Contains(personId))
                    {
                        rowValid = false;

                        // Remove person id from list so that list can be used later to optionally
                        // add rows for remaining people who were in the dataview, but not in the
                        // result set
                        dataViewPersonIds.Remove( personId );
                    }
                }

                if ( rowValid )
                {
                    // Set the first ever information for each row
                    bool isFirstEverGift = false;
                    DateTime firstGift = (DateTime)row["FirstGift"];
                    if ( firstEverVals.ContainsKey( personId ) )
                    {
                        DateTime firstEverGift = firstEverVals[personId];
                        isFirstEverGift = firstEverGift.Equals( firstGift );

                        row["FirstEverGift"] = firstEverGift;
                    }

                    // If only first time givers should be included, remove any that are not
                    if ( radFirstTime.Checked && !isFirstEverGift )
                    {
                        rowValid = false;
                    }
                    else
                    {
                        row["IsFirstEverGift"] = isFirstEverGift;
                    }
                }

                if ( !rowValid )
                {
                    row.Delete();
                }
            }

            // if dataview was selected and it includes people not in the result set,
            if ( dataViewId.HasValue && rblDataViewAction.SelectedValue == "All" && dataViewPersonIds.Any() )
            {
                // Query for the names of each of these people
                foreach( var person in personService
                    .Queryable().AsNoTracking()
                    .Select( p => new {
                        p.Id,
                        p.Guid,
                        p.NickName,
                        p.LastName,
                        p.Email
                    }))
                {
                    // Check for a first ever gift date
                    var firstEverGiftDate = firstEverVals
                        .Where( f => f.Key == person.Id )
                        .Select( f => f.Value )
                        .FirstOrDefault();

                    DataRow row = dtResults.NewRow();
                    row["Id"] = person.Id;
                    row["Guid"] = person.Guid;
                    row["NickName"] = person.NickName;
                    row["LastName"] = person.LastName;
                    row["PersonName"] = person.NickName + " " + person.LastName;
                    row["Email"] = person.Email;
                    row["IsFirstEverGift"] = false;
                    row["FirstEverGift"] = firstEverGiftDate;
                    dtResults.Rows.Add( row );
                }
            }

            // Update the changes (deletes) in the datatable
            dtResults.AcceptChanges();

            // Calculate Total
            if ( viewBy == GiversViewBy.Giver )
            {
                pnlTotal.Visible = true;
                object amountTotalObj = dtResults.Compute( "Sum(TotalAmount)", null );
                if ( amountTotalObj != null )
                {
                    decimal amountTotal = amountTotalObj.ToString().AsDecimal();
                    lTotal.Text = amountTotal.FormatAsCurrency();
                }
                else
                {
                    lTotal.Text = string.Empty;
                }
            }
            else
            {
                pnlTotal.Visible = false;
            }

            // Sort the results
            System.Data.DataView dv = dtResults.DefaultView;
            if ( gGiversGifts.SortProperty != null )
            {
                try
                {
                    var sortProperties = new List<string>();
                    foreach( string prop in gGiversGifts.SortProperty.Property.SplitDelimitedValues(false))
                    {
                        sortProperties.Add( string.Format( "[{0}] {1}", prop, gGiversGifts.SortProperty.DirectionString ) );
                    }
                    dv.Sort = sortProperties.AsDelimited( ", " );
                }
                catch
                {
                    dv.Sort = "[LastName] ASC, [NickName] ASC";
                }
            }
            else
            {
                dv.Sort = "[LastName] ASC, [NickName] ASC";
            }

            gGiversGifts.DataSource = dv;
            gGiversGifts.DataBind();
        }
예제 #20
0
        /// <summary>
        /// Shows the financial batch summary.
        /// </summary>
        /// <param name="batch">The financial batch.</param>
        private void ShowReadonlyDetails( FinancialBatch batch )
        {
            SetEditMode( false );

            if ( batch != null )
            {
                hfBatchId.SetValue( batch.Id );

                SetHeadingInfo( batch, batch.Name );

                string campusName = string.Empty;
                if ( batch.CampusId.HasValue )
                {
                    var campus = CampusCache.Read( batch.CampusId.Value );
                    if ( campus != null )
                    {
                        campusName = campus.ToString();
                    }
                }

                var rockContext = new RockContext();
                var financialTransactionService = new FinancialTransactionService( rockContext );
                var batchTransactions = financialTransactionService.Queryable().Where( a => a.BatchId.HasValue && a.BatchId.Value == batch.Id );

                var financialTransactionDetailService = new FinancialTransactionDetailService( rockContext );
                var qryTransactionDetails = financialTransactionDetailService.Queryable().Where( a => a.Transaction.BatchId == batch.Id );
                decimal txnTotal = qryTransactionDetails.Select( a => (decimal?)a.Amount ).Sum() ?? 0;

                decimal variance = txnTotal - batch.ControlAmount;
                string amountFormat = string.Format(
                    "{0} / {1} / " + ( variance == 0.0M ? "{2}" : "<span class='label label-danger'>{2}</span>" ),
                    txnTotal.FormatAsCurrency(),
                    batch.ControlAmount.FormatAsCurrency(),
                    variance.FormatAsCurrency() );

                lDetails.Text = new DescriptionList()
                    .Add( "Date Range", new DateRange( batch.BatchStartDateTime, batch.BatchEndDateTime ).ToString( "g" ) )
                    .Add( "Transaction / Control / Variance", amountFormat )
                    .Add( "Accounting Code", batch.AccountingSystemCode )
                    .Add( "Notes", batch.Note )
                    .Html;

                // Account Summary
                gAccounts.DataSource = qryTransactionDetails
                    .GroupBy( d => new
                    {
                        AccountId = d.AccountId,
                        AccountName = d.Account.Name
                    } )
                    .Select( s => new
                    {
                        Id = s.Key.AccountId,
                        Name = s.Key.AccountName,
                        Amount = s.Sum( a => (decimal?)a.Amount ) ?? 0.0M
                    } )
                    .OrderBy( s => s.Name )
                    .ToList();

                gAccounts.DataBind();

                // Currency Summary
                gCurrencyTypes.DataSource = batchTransactions
                    .GroupBy( c => new
                    {
                        CurrencyTypeValueId = c.FinancialPaymentDetailId.HasValue ? c.FinancialPaymentDetail.CurrencyTypeValueId : 0,
                    } )
                    .Select( s => new
                    {
                        CurrencyTypeValueId = s.Key.CurrencyTypeValueId,
                        Amount = s.Sum( a => (decimal?)a.TransactionDetails.Sum( t => t.Amount ) ) ?? 0.0M
                    } )
                    .ToList()
                    .Select( s => new
                    {
                        Id = s.CurrencyTypeValueId,
                        Name = DefinedValueCache.GetName( s.CurrencyTypeValueId ),
                        Amount = s.Amount
                    } ).OrderBy( a => a.Name ).ToList();

                gCurrencyTypes.DataBind();
            }
        }
        /// <summary>
        /// Handles the Delete event of the gTransactionDetails control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="Rock.Web.UI.Controls.RowEventArgs"/> instance containing the event data.</param>
        protected void gTransactionDetails_Delete( object sender, Rock.Web.UI.Controls.RowEventArgs e )
        {
            var rockContext = new RockContext();
            var ftdService = new FinancialTransactionDetailService( rockContext );
            var ftd = ftdService.Get( e.RowKeyId );
            if ( ftd != null )
            {
                string errorMessage;
                if ( !ftdService.CanDelete( ftd, out errorMessage ) )
                {
                    maGridWarning.Show( errorMessage, Rock.Web.UI.Controls.ModalAlertType.Information );
                    return;
                }

                ftdService.Delete( ftd );
                rockContext.SaveChanges();
            }

            FinancialTransaction transaction = new FinancialTransaction();
            transaction = new FinancialTransactionService( rockContext ).Get( hfIdTransValue.ValueAsInt() );
            BindTransactionDetailGrid( transaction );
        }