/// <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> /// 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(); } }
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(); } }
/// <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 ); } }
/// <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 ); } }
/// <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(); }
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(); } }
/// <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> /// 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 ); } }