Beispiel #1
0
        /// <summary>
        /// Publishes the expiring card and cardholder details
        /// </summary>
        /// <param name="person"></param>
        /// <param name="financialPaymentDetail"></param>
        /// <param name="financialScheduledTransactions"></param>
        public static void Publish(Person person, FinancialPaymentDetail financialPaymentDetail, List <int> financialScheduledTransactions)
        {
            if (!RockMessageBus.IsRockStarted)
            {
                // Don't publish events until Rock is all the way started
                const string logMessage = "'Credit Card Is Expiring Message' message was not published because Rock is not fully started yet.";

                var elapsedSinceProcessStarted = RockDateTime.Now - RockInstanceConfig.ApplicationStartedDateTime;

                if (elapsedSinceProcessStarted.TotalSeconds > RockMessageBus.MAX_SECONDS_SINCE_STARTTIME_LOG_ERROR)
                {
                    RockLogger.Log.Error(RockLogDomains.Bus, logMessage);
                    ExceptionLogService.LogException(new BusException(logMessage));
                }
                else
                {
                    RockLogger.Log.Debug(RockLogDomains.Bus, logMessage);
                }

                return;
            }

            var cardHolder = new CardHolder()
            {
                CommunicationPreference = (int)person.CommunicationPreference,
                Email      = person.Email,
                FirstName  = person.FirstName,
                Id         = person.Id,
                LastName   = person.LastName,
                MiddleName = person.MiddleName,
                NickName   = person.NickName
            };

            var message = new CreditCardIsExpiringMessage
            {
                AccountNumberMasked             = financialPaymentDetail.AccountNumberMasked,
                BillingLocation                 = financialPaymentDetail.BillingLocation?.GetFullStreetAddress(),
                CardExpirationDate              = financialPaymentDetail.CardExpirationDate,
                CreatedDateTime                 = financialPaymentDetail.CreatedDateTime,
                CreditCardTypeValue             = financialPaymentDetail.CreditCardTypeValue?.Value,
                ExpirationDate                  = financialPaymentDetail.ExpirationDate,
                ExpirationMonth                 = financialPaymentDetail.ExpirationMonth,
                ExpirationYear                  = financialPaymentDetail.ExpirationYear,
                FinancialPersonSavedAccountName = financialPaymentDetail.FinancialPersonSavedAccount?.Name,
                Id         = financialPaymentDetail.Id,
                NameOnCard = financialPaymentDetail.NameOnCard,
                Person     = cardHolder,
                FinancialScheduledTransactions = financialScheduledTransactions
            };

            _ = RockMessageBus.PublishAsync <ExpiringCardEventQueue, CreditCardIsExpiringMessage>(message);

            RockLogger.Log.Debug(RockLogDomains.Bus, "Published 'Credit Card Is Expiring Message' message.");
        }
Beispiel #2
0
        /// <summary>
        /// Creates the payment detail.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="person">The person.</param>
        /// <param name="billingLocationId">The billing location identifier.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private FinancialPaymentDetail CreatePaymentDetail(PaymentParameters parameters, Person person, int billingLocationId, RockContext rockContext)
        {
            if (string.IsNullOrWhiteSpace(parameters.AccountNumber))
            {
                GenerateResponse(HttpStatusCode.BadRequest, "AccountNumber is required");
                return(null);
            }

            if (string.IsNullOrWhiteSpace(parameters.AccountType))
            {
                GenerateResponse(HttpStatusCode.BadRequest, "AccountType is required");
                return(null);
            }

            var accountType  = parameters.AccountType.ToLower();
            var allowedTypes = new String[] { "checking", "savings", "credit" };

            if (!allowedTypes.Contains(accountType))
            {
                GenerateResponse(HttpStatusCode.BadRequest, "AccountType must be one of " + string.Join(", ", allowedTypes));
                return(null);
            }

            var maskedAccountNumber = Mask(parameters.AccountNumber);
            var nameOnCard          = (parameters.FirstName ?? person.FirstName) + " " + (parameters.LastName ?? person.LastName);

            var paymentDetail = new FinancialPaymentDetail
            {
                AccountNumberMasked = maskedAccountNumber,
                NameOnCardEncrypted = Rock.Security.Encryption.EncryptString(nameOnCard),
                BillingLocationId   = billingLocationId
            };

            if (parameters.AccountType.ToLower() == "credit")
            {
                paymentDetail.ExpirationMonthEncrypted = Rock.Security.Encryption.EncryptString(parameters.ExpirationMonth.ToString());
                paymentDetail.ExpirationYearEncrypted  = Rock.Security.Encryption.EncryptString(parameters.ExpirationYear.ToString());
            }

            new FinancialPaymentDetailService(rockContext).Add(paymentDetail);
            rockContext.SaveChanges();
            return(paymentDetail);
        }
        private static FinancialPaymentDetail CreateFinancialPaymentDetail(
            int?currencyTypeId,
            int?cardTypeId,
            DateTime transactionDateTime)
        {
            var payment = new FinancialPaymentDetail
            {
                CurrencyTypeValueId   = currencyTypeId,
                CreditCardTypeValueId = cardTypeId,
                Guid             = Guid.NewGuid(),
                CreatedDateTime  = transactionDateTime,
                ModifiedDateTime = RockDateTime.Now
            };

            _paymentService.Add(payment);
            _rockContext.SaveChanges(true);

            return(payment);
        }
Beispiel #4
0
        /// <summary>
        /// Handles the Click event of the btnConfirmationNext 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 btnPayPalConfirmationNext_Click(object sender, EventArgs e)
        {
            string errorMessage = string.Empty;

            var transaction = _payPalExpressGatewayComponent.Charge(_payPalExpressGateway, GetPaymentInfo(), out errorMessage);

            if (errorMessage != string.Empty)
            {
                ShowMessage(NotificationBoxType.Danger, "Payment Processing Error", errorMessage);
                return;
            }
            if (transaction == null)
            {
                ShowMessage(NotificationBoxType.Danger, "Payment Error", "Invalid Transaction");
                return;
            }
            Person      person      = GetPerson(GetPaymentInfo(), true);
            RockContext rockContext = new RockContext();

            SaveTransaction(_payPalExpressGateway, _payPalExpressGatewayComponent, person, GetPaymentInfo(), transaction, rockContext);
            FinancialPaymentDetail paymentDetail = transaction.FinancialPaymentDetail.Clone(false);

            ShowSuccess(_payPalExpressGatewayComponent, person, GetPaymentInfo(), null, paymentDetail, rockContext);
        }
        /// <summary>
        /// Gets the payment information.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="person">The person.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="totalAmount">The total amount.</param>
        /// <param name="paymentDetail">The payment detail.</param>
        /// <returns></returns>
        private PaymentInfo GetPaymentInfo( PaymentParameters parameters, Person person, RockContext rockContext, decimal totalAmount, FinancialPaymentDetail paymentDetail )
        {
            PaymentInfo paymentInfo = null;

            if ( parameters.AccountType.ToLower() == "credit" )
            {
                if ( parameters.ExpirationMonth < 1 || parameters.ExpirationMonth > 12 )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "ExpirationMonth is required and must be between 1 and 12 for credit transactions" );
                }

                var currentDate = DateTime.Now;
                var maxYear = currentDate.Year + 30;

                if ( parameters.ExpirationYear < currentDate.Year || parameters.ExpirationYear > maxYear )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, string.Format( "ExpirationYear is required and must be between {0} and {1} for credit transactions", currentDate.Year, maxYear ) );
                }

                if ( parameters.ExpirationYear <= currentDate.Year && parameters.ExpirationMonth < currentDate.Month )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "The ExpirationMonth and ExpirationYear combination must not have already elapsed for credit transactions" );
                }

                if ( string.IsNullOrWhiteSpace( parameters.Street1 ) ||
                    string.IsNullOrWhiteSpace( parameters.City ) ||
                    string.IsNullOrWhiteSpace( parameters.State ) ||
                    string.IsNullOrWhiteSpace( parameters.PostalCode ) )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "Street1, City, State, and PostalCode are required for credit transactions" );
                }

                paymentInfo = new CreditCardPaymentInfo()
                {
                    Number = parameters.AccountNumber,
                    Code = parameters.CCV ?? string.Empty,
                    ExpirationDate = new DateTime( parameters.ExpirationYear, parameters.ExpirationMonth, 1 ),
                    BillingStreet1 = parameters.Street1 ?? string.Empty,
                    BillingStreet2 = parameters.Street2 ?? string.Empty,
                    BillingCity = parameters.City ?? string.Empty,
                    BillingState = parameters.State ?? string.Empty,
                    BillingPostalCode = parameters.PostalCode ?? string.Empty,
                    BillingCountry = parameters.Country ?? "USA"
                };
            }
            else
            {
                if ( string.IsNullOrWhiteSpace( parameters.RoutingNumber ) )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "RoutingNumber is required for ACH transactions" );
                    return null;
                }

                paymentInfo = new ACHPaymentInfo()
                {
                    BankRoutingNumber = parameters.RoutingNumber,
                    BankAccountNumber = parameters.AccountNumber,
                    AccountType = parameters.AccountType.ToLower() == "checking" ? BankAccountType.Checking : BankAccountType.Savings
                };
            }

            paymentInfo.Amount = totalAmount;
            paymentInfo.FirstName = parameters.FirstName ?? person.FirstName;
            paymentInfo.LastName = parameters.LastName ?? person.LastName;
            paymentInfo.Email = parameters.Email ?? person.Email;
            paymentInfo.Phone = parameters.PhoneNumber ?? string.Empty;
            paymentInfo.Street1 = parameters.Street1 ?? string.Empty;
            paymentInfo.Street2 = parameters.Street2 ?? string.Empty;
            paymentInfo.City = parameters.City ?? string.Empty;
            paymentInfo.State = parameters.State ?? string.Empty;
            paymentInfo.PostalCode = parameters.PostalCode ?? string.Empty;
            paymentInfo.Country = parameters.Country ?? "USA";

            if ( paymentInfo.CreditCardTypeValue != null )
            {
                paymentDetail.CreditCardTypeValueId = paymentInfo.CreditCardTypeValue.Id;
            }

            if ( paymentInfo.CurrencyTypeValue != null )
            {
                paymentDetail.CurrencyTypeValueId = paymentInfo.CurrencyTypeValue.Id;
            }

            return paymentInfo;
        }
        /// <summary>
        /// Creates the saved account.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="paymentDetail">The payment detail.</param>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="person">The person.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private FinancialPersonSavedAccount CreateSavedAccount( PaymentParameters parameters, FinancialPaymentDetail paymentDetail, FinancialGateway financialGateway, Person person, RockContext rockContext)
        {
            var lastFour = paymentDetail.AccountNumberMasked.Substring(paymentDetail.AccountNumberMasked.Length - 4);
            var name = string.Empty;

            if ( parameters.AccountType.ToLower() != "credit" )
            {
                if ( string.IsNullOrWhiteSpace( parameters.RoutingNumber ) )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "RoutingNumber is required for ACH transactions" );
                    return null;
                }

                if ( string.IsNullOrWhiteSpace( parameters.AccountNumber ) )
                {
                    GenerateResponse( HttpStatusCode.BadRequest, "AccountNumber is required" );
                    return null;
                }

                name = "Bank card ***" + lastFour;
                var bankAccountService = new FinancialPersonBankAccountService( rockContext );
                var accountNumberSecured = FinancialPersonBankAccount.EncodeAccountNumber( parameters.RoutingNumber, parameters.AccountNumber );
                var bankAccount = bankAccountService.Queryable().Where( a =>
                    a.AccountNumberSecured == accountNumberSecured &&
                    a.PersonAliasId == person.PrimaryAliasId.Value ).FirstOrDefault();

                if ( bankAccount == null )
                {
                    bankAccount = new FinancialPersonBankAccount();
                    bankAccount.PersonAliasId = person.PrimaryAliasId.Value;
                    bankAccount.AccountNumberMasked = paymentDetail.AccountNumberMasked;
                    bankAccount.AccountNumberSecured = accountNumberSecured;
                    bankAccountService.Add( bankAccount );
                }
            }
            else
            {
                name = "Credit card ***" + lastFour;
            }

            var savedAccount = new FinancialPersonSavedAccount {
                PersonAliasId = person.PrimaryAliasId,
                FinancialGatewayId = financialGateway.Id,
                Name = name,
                FinancialPaymentDetailId = paymentDetail.Id
            };

            new FinancialPersonSavedAccountService(rockContext).Add( savedAccount );
            rockContext.SaveChanges();
            return savedAccount;
        }
        /// <summary>
        /// Creates the payment detail.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="person">The person.</param>
        /// <param name="billingLocationId">The billing location identifier.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private FinancialPaymentDetail CreatePaymentDetail( PaymentParameters parameters, Person person, int billingLocationId, RockContext rockContext )
        {
            if ( string.IsNullOrWhiteSpace( parameters.AccountNumber ) )
            {
                GenerateResponse( HttpStatusCode.BadRequest, "AccountNumber is required" );
                return null;
            }

            if ( string.IsNullOrWhiteSpace( parameters.AccountType ) )
            {
                GenerateResponse( HttpStatusCode.BadRequest, "AccountType is required" );
                return null;
            }

            var accountType = parameters.AccountType.ToLower();
            var allowedTypes = new String[] { "checking", "savings", "credit" };

            if (!allowedTypes.Contains(accountType) )
            {
                GenerateResponse( HttpStatusCode.BadRequest, "AccountType must be one of " + string.Join(", ", allowedTypes) );
                return null;
            }

            var maskedAccountNumber = Mask( parameters.AccountNumber );
            var nameOnCard = ( parameters.FirstName ?? person.FirstName ) + " " + ( parameters.LastName ?? person.LastName );

            var paymentDetail = new FinancialPaymentDetail
            {
                AccountNumberMasked = maskedAccountNumber,
                NameOnCardEncrypted = Rock.Security.Encryption.EncryptString(nameOnCard),
                BillingLocationId = billingLocationId
            };

            if ( parameters.AccountType.ToLower() == "credit" )
            {
                paymentDetail.ExpirationMonthEncrypted = Rock.Security.Encryption.EncryptString( parameters.ExpirationMonth.ToString() );
                paymentDetail.ExpirationYearEncrypted = Rock.Security.Encryption.EncryptString( parameters.ExpirationYear.ToString() );
            }

            new FinancialPaymentDetailService( rockContext ).Add( paymentDetail );
            rockContext.SaveChanges();
            return paymentDetail;
        }
Beispiel #8
0
        /// <summary>
        /// Maps the contribution.
        /// </summary>
        /// <param name="tableData">The table data.</param>
        /// <param name="selectedColumns">The selected columns.</param>
        private void MapContribution( IQueryable<Row> tableData, List<string> selectedColumns = null )
        {
            var lookupContext = new RockContext();
            int transactionEntityTypeId = EntityTypeCache.Read( "Rock.Model.FinancialTransaction" ).Id;
            var transactionTypeContributionId = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ), lookupContext ).Id;

            var currencyTypes = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE ) );
            int currencyTypeACH = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH ) ) ).Id;
            int currencyTypeCash = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH ) ) ).Id;
            int currencyTypeCheck = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK ) ) ).Id;
            int currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) ).Id;
            int? currencyTypeNonCash = currencyTypes.DefinedValues.Where( dv => dv.Value.Equals( "Non-Cash" ) ).Select( dv => (int?)dv.Id ).FirstOrDefault();
            if ( currencyTypeNonCash == null )
            {
                var newTenderNonCash = new DefinedValue();
                newTenderNonCash.Value = "Non-Cash";
                newTenderNonCash.Description = "Non-Cash";
                newTenderNonCash.DefinedTypeId = currencyTypes.Id;
                lookupContext.DefinedValues.Add( newTenderNonCash );
                lookupContext.SaveChanges();

                currencyTypeNonCash = newTenderNonCash.Id;
            }

            var creditCardTypes = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE ) ).DefinedValues;

            int sourceTypeOnsite = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_ONSITE_COLLECTION ), lookupContext ).Id;
            int sourceTypeWebsite = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE ), lookupContext ).Id;
            int sourceTypeKiosk = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_KIOSK ), lookupContext ).Id;

            var refundReasons = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON ), lookupContext ).DefinedValues;

            var accountList = new FinancialAccountService( lookupContext ).Queryable().AsNoTracking().ToList();

            int? defaultBatchId = null;
            if ( ImportedBatches.ContainsKey( 0 ) )
            {
                defaultBatchId = ImportedBatches[0];
            }

            // Get all imported contributions
            var importedContributions = new FinancialTransactionService( lookupContext ).Queryable().AsNoTracking()
               .Where( c => c.ForeignId != null )
               .ToDictionary( t => (int)t.ForeignId, t => (int?)t.Id );

            // List for batching new contributions
            var newTransactions = new List<FinancialTransaction>();

            int completed = 0;
            int totalRows = tableData.Count();
            int percentage = ( totalRows - 1 ) / 100 + 1;
            ReportProgress( 0, string.Format( "Verifying contribution import ({0:N0} found, {1:N0} already exist).", totalRows, importedContributions.Count ) );
            foreach ( var row in tableData.Where( r => r != null ) )
            {
                int? individualId = row["Individual_ID"] as int?;
                int? householdId = row["Household_ID"] as int?;
                int? contributionId = row["ContributionID"] as int?;

                if ( contributionId != null && !importedContributions.ContainsKey( (int)contributionId ) )
                {
                    var transaction = new FinancialTransaction();
                    transaction.CreatedByPersonAliasId = ImportPersonAliasId;
                    transaction.ModifiedByPersonAliasId = ImportPersonAliasId;
                    transaction.TransactionTypeValueId = transactionTypeContributionId;
                    transaction.ForeignKey = contributionId.ToString();
                    transaction.ForeignId = contributionId;

                    int? giverAliasId = null;
                    var personKeys = GetPersonKeys( individualId, householdId );
                    if ( personKeys != null && personKeys.PersonAliasId > 0 )
                    {
                        giverAliasId = personKeys.PersonAliasId;
                        transaction.CreatedByPersonAliasId = giverAliasId;
                        transaction.AuthorizedPersonAliasId = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }

                    string summary = row["Memo"] as string;
                    if ( summary != null )
                    {
                        transaction.Summary = summary;
                    }

                    int? batchId = row["BatchID"] as int?;
                    if ( batchId != null && ImportedBatches.Any( b => b.Key.Equals( batchId ) ) )
                    {
                        transaction.BatchId = ImportedBatches.FirstOrDefault( b => b.Key.Equals( batchId ) ).Value;
                    }
                    else
                    {
                        // use the default batch for any non-matching transactions
                        transaction.BatchId = defaultBatchId;
                    }

                    DateTime? receivedDate = row["Received_Date"] as DateTime?;
                    if ( receivedDate != null )
                    {
                        transaction.TransactionDateTime = receivedDate;
                        transaction.CreatedDateTime = receivedDate;
                        transaction.ModifiedDateTime = ImportDateTime;
                    }

                    string cardType = row["Card_Type"] as string;
                    string cardLastFour = row["Last_Four"] as string;
                    string contributionType = row["Contribution_Type_Name"].ToStringSafe().ToLower();
                    if ( contributionType != null )
                    {
                        // set default source to onsite, exceptions listed below
                        transaction.SourceTypeValueId = sourceTypeOnsite;

                        int? paymentCurrencyTypeId = null, creditCardTypeId = null;

                        if ( contributionType == "cash" )
                        {
                            paymentCurrencyTypeId = currencyTypeCash;
                        }
                        else if ( contributionType == "check" )
                        {
                            paymentCurrencyTypeId = currencyTypeCheck;
                        }
                        else if ( contributionType == "ach" )
                        {
                            paymentCurrencyTypeId = currencyTypeACH;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else if ( contributionType == "credit card" )
                        {
                            paymentCurrencyTypeId = currencyTypeCreditCard;
                            transaction.SourceTypeValueId = sourceTypeWebsite;

                            if ( cardType != null )
                            {
                                creditCardTypeId = creditCardTypes.Where( t => t.Value.Equals( cardType ) ).Select( t => (int?)t.Id ).FirstOrDefault();
                            }
                        }
                        else
                        {
                            paymentCurrencyTypeId = currencyTypeNonCash;
                        }

                        var paymentDetail = new FinancialPaymentDetail();
                        paymentDetail.CreatedDateTime = receivedDate;
                        paymentDetail.CreatedByPersonAliasId = giverAliasId;
                        paymentDetail.ModifiedDateTime = ImportDateTime;
                        paymentDetail.ModifiedByPersonAliasId = giverAliasId;
                        paymentDetail.CurrencyTypeValueId = paymentCurrencyTypeId;
                        paymentDetail.CreditCardTypeValueId = creditCardTypeId;
                        paymentDetail.AccountNumberMasked = cardLastFour;
                        paymentDetail.ForeignKey = contributionId.ToString();
                        paymentDetail.ForeignId = contributionId;

                        transaction.FinancialPaymentDetail = paymentDetail;
                    }

                    string checkNumber = row["Check_Number"] as string;
                    // if the check number is valid, put it in the transaction code
                    if ( checkNumber.AsType<int?>() != null )
                    {
                        transaction.TransactionCode = checkNumber;
                    }
                    // check for SecureGive kiosk transactions
                    else if ( !string.IsNullOrEmpty( checkNumber ) && checkNumber.StartsWith( "SG" ) )
                    {
                        transaction.SourceTypeValueId = sourceTypeKiosk;
                    }

                    string fundName = row["Fund_Name"] as string;
                    string subFund = row["Sub_Fund_Name"] as string;
                    string fundGLAccount = row["Fund_GL_Account"] as string;
                    string subFundGLAccount = row["Sub_Fund_GL_Account"] as string;
                    Boolean? isFundActive = row["Fund_Is_active"] as Boolean?;
                    decimal? statedValue = row["Stated_Value"] as decimal?;
                    decimal? amount = row["Amount"] as decimal?;
                    if ( fundName != null & amount != null )
                    {
                        int transactionAccountId;
                        var parentAccount = accountList.FirstOrDefault( a => a.Name.Equals( fundName ) && a.CampusId == null );
                        if ( parentAccount == null )
                        {
                            parentAccount = AddAccount( lookupContext, fundName, fundGLAccount, null, null, isFundActive );
                            accountList.Add( parentAccount );
                        }

                        if ( subFund != null )
                        {
                            int? campusFundId = null;
                            // assign a campus if the subfund is a campus fund
                            var campusFund = CampusList.FirstOrDefault( c => subFund.StartsWith( c.Name ) || subFund.StartsWith( c.ShortCode ) );
                            if ( campusFund != null )
                            {
                                // use full campus name as the subfund
                                subFund = campusFund.Name;
                                campusFundId = campusFund.Id;
                            }

                            // add info to easily find/assign this fund in the view
                            subFund = string.Format( "{0} {1}", subFund, fundName );

                            var childAccount = accountList.FirstOrDefault( c => c.Name.Equals( subFund ) && c.ParentAccountId == parentAccount.Id );
                            if ( childAccount == null )
                            {
                                // create a child account with a campusId if it was set
                                childAccount = AddAccount( lookupContext, subFund, subFundGLAccount, campusFundId, parentAccount.Id, isFundActive );
                                accountList.Add( childAccount );
                            }

                            transactionAccountId = childAccount.Id;
                        }
                        else
                        {
                            transactionAccountId = parentAccount.Id;
                        }

                        if ( amount == 0 && statedValue != null && statedValue != 0 )
                        {
                            amount = statedValue;
                        }

                        var transactionDetail = new FinancialTransactionDetail();
                        transactionDetail.Amount = (decimal)amount;
                        transactionDetail.CreatedDateTime = receivedDate;
                        transactionDetail.AccountId = transactionAccountId;
                        transaction.TransactionDetails.Add( transactionDetail );

                        if ( amount < 0 )
                        {
                            transaction.RefundDetails = new FinancialTransactionRefund();
                            transaction.RefundDetails.CreatedDateTime = receivedDate;
                            transaction.RefundDetails.RefundReasonValueId = refundReasons.Where( dv => summary != null && dv.Value.Contains( summary ) )
                                .Select( dv => (int?)dv.Id ).FirstOrDefault();
                            transaction.RefundDetails.RefundReasonSummary = summary;
                        }
                    }

                    newTransactions.Add( transaction );
                    completed++;
                    if ( completed % percentage < 1 )
                    {
                        int percentComplete = completed / percentage;
                        ReportProgress( percentComplete, string.Format( "{0:N0} contributions imported ({1}% complete).", completed, percentComplete ) );
                    }
                    else if ( completed % ReportingNumber < 1 )
                    {
                        SaveContributions( newTransactions );
                        newTransactions.Clear();
                        ReportPartialProgress();
                    }
                }
            }

            if ( newTransactions.Any() )
            {
                SaveContributions( newTransactions );
            }

            ReportProgress( 100, string.Format( "Finished contribution import: {0:N0} contributions imported.", completed ) );
        }
Beispiel #9
0
        /// <summary>
        /// Uploads the scanned item.
        /// </summary>
        /// <param name="scannedDocInfo">The scanned document information.</param>
        public static void UploadScannedItem(ScannedDocInfo scannedDocInfo)
        {
            RockRestClient client = EnsureUploadScanRestClient();

            // upload image of front of doc (if was successfully scanned)
            int?frontImageBinaryFileId = null;

            if (scannedDocInfo.FrontImageData != null)
            {
                string frontImageFileName = string.Format("image1_{0}.png", DateTime.Now.ToString("o").RemoveSpecialCharacters());
                frontImageBinaryFileId = client.UploadBinaryFile(frontImageFileName, Rock.Client.SystemGuid.BinaryFiletype.CONTRIBUTION_IMAGE.AsGuid(), scannedDocInfo.FrontImagePngBytes, false);
            }

            // upload image of back of doc (if it exists)
            int?backImageBinaryFileId = null;

            if (scannedDocInfo.BackImageData != null)
            {
                // upload image of back of doc
                string backImageFileName = string.Format("image2_{0}.png", DateTime.Now.ToString("o").RemoveSpecialCharacters());
                backImageBinaryFileId = client.UploadBinaryFile(backImageFileName, Rock.Client.SystemGuid.BinaryFiletype.CONTRIBUTION_IMAGE.AsGuid(), scannedDocInfo.BackImagePngBytes, false);
            }

            FinancialPaymentDetail financialPaymentDetail = new FinancialPaymentDetail();

            financialPaymentDetail.CurrencyTypeValueId = scannedDocInfo.CurrencyTypeValue.Id;
            financialPaymentDetail.Guid = Guid.NewGuid();
            var financialPaymentDetailId = client.PostData <FinancialPaymentDetail>("api/FinancialPaymentDetails", financialPaymentDetail).AsIntegerOrNull();

            FinancialTransaction financialTransaction = new FinancialTransaction();

            financialTransaction.BatchId         = batchPage.SelectedFinancialBatch.Id;
            financialTransaction.TransactionCode = string.Empty;
            financialTransaction.Summary         = string.Empty;

            financialTransaction.Guid = Guid.NewGuid();
            financialTransaction.TransactionDateTime = batchPage.SelectedFinancialBatch.BatchStartDateTime;

            financialTransaction.FinancialPaymentDetailId = financialPaymentDetailId;
            financialTransaction.SourceTypeValueId        = scannedDocInfo.SourceTypeValue.Id;

            financialTransaction.TransactionTypeValueId = transactionTypeValueContribution.Id;
            var accounts = scannedDocInfo.AccountAmountCaptureList;

            if (accounts != null)
            {
                var accountsWithValues = accounts.Where(a => a.Amount > 0).ToList();
                if (accountsWithValues != null && accountsWithValues.Count() > 0)
                {
                    AddFinancialTransactionDetailForEachAccount(accountsWithValues, financialTransaction);
                }
            }
            int?uploadedTransactionId;

            if (scannedDocInfo.IsCheck)
            {
                financialTransaction.TransactionCode = scannedDocInfo.CheckNumber;
                financialTransaction.MICRStatus      = scannedDocInfo.BadMicr ? MICRStatus.Fail : MICRStatus.Success;

                FinancialTransactionScannedCheck financialTransactionScannedCheck = new FinancialTransactionScannedCheck();

                // Rock server will encrypt CheckMicrPlainText to this since we can't have the DataEncryptionKey in a RestClient
                financialTransactionScannedCheck.FinancialTransaction  = financialTransaction;
                financialTransactionScannedCheck.ScannedCheckMicrData  = scannedDocInfo.ScannedCheckMicrData;
                financialTransactionScannedCheck.ScannedCheckMicrParts = scannedDocInfo.ScannedCheckMicrParts;
                uploadedTransactionId = client.PostData <FinancialTransactionScannedCheck>("api/FinancialTransactions/PostScanned", financialTransactionScannedCheck).AsIntegerOrNull();
            }
            else
            {
                //FinancialTransactionDetail
                uploadedTransactionId = client.PostData <FinancialTransaction>("api/FinancialTransactions", financialTransaction as FinancialTransaction).AsIntegerOrNull();
            }

            // upload FinancialTransactionImage records for front/back
            if (frontImageBinaryFileId.HasValue)
            {
                FinancialTransactionImage financialTransactionImageFront = new FinancialTransactionImage();
                financialTransactionImageFront.BinaryFileId  = frontImageBinaryFileId.Value;
                financialTransactionImageFront.TransactionId = uploadedTransactionId.Value;
                financialTransactionImageFront.Order         = 0;
                financialTransactionImageFront.Guid          = Guid.NewGuid();
                client.PostData <FinancialTransactionImage>("api/FinancialTransactionImages", financialTransactionImageFront);
            }

            if (backImageBinaryFileId.HasValue)
            {
                FinancialTransactionImage financialTransactionImageBack = new FinancialTransactionImage();
                financialTransactionImageBack.BinaryFileId  = backImageBinaryFileId.Value;
                financialTransactionImageBack.TransactionId = uploadedTransactionId.Value;
                financialTransactionImageBack.Order         = 1;
                financialTransactionImageBack.Guid          = Guid.NewGuid();
                client.PostData <FinancialTransactionImage>("api/FinancialTransactionImages", financialTransactionImageBack);
            }

            scannedDocInfo.TransactionId         = uploadedTransactionId;
            financialTransaction.Id              = uploadedTransactionId ?? 0;
            financialTransaction.CreatedDateTime = financialTransaction.CreatedDateTime ?? DateTime.Now;
            batchPage.SelectedFinancialBatch.Transactions.Add(financialTransaction);

            var transactionList = batchPage.grdBatchItems.DataContext as BindingList <FinancialTransaction>;

            transactionList.Insert(0, financialTransaction);

            ItemsUploaded++;
        }
Beispiel #10
0
        public HttpResponseMessage Give([FromBody] GiveParameters giveParameters)
        {
            var rockContext = new RockContext();

            try
            {
                rockContext.WrapTransaction(() =>
                {
                    int?locationId = null;
                    FinancialPaymentDetail paymentDetail = null;
                    PaymentInfo paymentInfo = null;
                    FinancialPersonSavedAccount savedAccount = null;
                    bool newSavedAccount = true;

                    var gatewayComponent = GatewayContainer.GetComponent(gatewayName);

                    if (gatewayComponent == null)
                    {
                        GenerateResponse(HttpStatusCode.InternalServerError, "There was a problem creating the gateway component");
                    }

                    var financialGateway = new FinancialGatewayService(rockContext).Queryable().FirstOrDefault(g => g.EntityTypeId == gatewayComponent.EntityType.Id);

                    if (financialGateway == null)
                    {
                        GenerateResponse(HttpStatusCode.InternalServerError, "There was a problem creating the financial gateway");
                    }

                    var totalAmount = CalculateTotalAmount(giveParameters, rockContext);
                    var person      = GetExistingPerson(giveParameters.PersonId, rockContext);

                    if (person == null)
                    {
                        // New person
                        locationId = CreateLocation(giveParameters, rockContext);
                        person     = CreatePerson(giveParameters, locationId.Value, rockContext);
                    }
                    else
                    {
                        // Existing person
                        savedAccount = GetExistingSavedAccount(giveParameters, person, rockContext);

                        if (savedAccount != null)
                        {
                            locationId      = savedAccount.FinancialPaymentDetail.BillingLocationId;
                            newSavedAccount = false;
                        }
                    }

                    if (!locationId.HasValue)
                    {
                        locationId = CreateLocation(giveParameters, rockContext);
                    }

                    if (savedAccount == null)
                    {
                        paymentDetail   = CreatePaymentDetail(giveParameters, person, locationId.Value, rockContext);
                        savedAccount    = CreateSavedAccount(giveParameters, paymentDetail, financialGateway, person, rockContext);
                        newSavedAccount = true;
                        paymentInfo     = GetPaymentInfo(giveParameters, person, rockContext, totalAmount.Value, paymentDetail);
                    }
                    else
                    {
                        paymentDetail = savedAccount.FinancialPaymentDetail;
                        locationId    = paymentDetail.BillingLocationId;
                        paymentInfo   = savedAccount.GetReferencePayment();
                        UpdatePaymentInfoForSavedAccount(giveParameters, paymentInfo, person, rockContext, locationId.Value, totalAmount.Value);
                    }

                    SaveLocationToFamilyIfNone(person, locationId.Value, rockContext);
                    string errorMessage;
                    var transaction = gatewayComponent.Charge(financialGateway, paymentInfo, out errorMessage);

                    if (transaction == null || !string.IsNullOrWhiteSpace(errorMessage))
                    {
                        GenerateResponse(HttpStatusCode.InternalServerError, errorMessage ?? "The gateway had a problem and/or did not create a transaction as expected");
                    }

                    transaction.FinancialPaymentDetail   = null;
                    transaction.SourceTypeValueId        = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE)).Id;
                    transaction.TransactionDateTime      = RockDateTime.Now;
                    transaction.AuthorizedPersonAliasId  = person.PrimaryAliasId;
                    transaction.AuthorizedPersonAlias    = person.PrimaryAlias;
                    transaction.FinancialGatewayId       = financialGateway.Id;
                    transaction.TransactionTypeValueId   = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION)).Id;
                    transaction.FinancialPaymentDetailId = paymentDetail.Id;
                    savedAccount.TransactionCode         = transaction.TransactionCode;

                    foreach (var accountAmount in giveParameters.AmountDetails)
                    {
                        transaction.TransactionDetails.Add(new FinancialTransactionDetail()
                        {
                            Amount    = accountAmount.Amount,
                            AccountId = accountAmount.TargetAccountId
                        });
                    }

                    new FinancialTransactionService(rockContext).Add(transaction);
                    rockContext.SaveChanges();

                    if (newSavedAccount)
                    {
                        var newReferenceNumber       = gatewayComponent.GetReferenceNumber(transaction, out errorMessage);
                        savedAccount.ReferenceNumber = newReferenceNumber;
                    }

                    rockContext.SaveChanges();
                });
            }
            catch (HttpResponseException exception)
            {
                return(exception.Response);
            }
            catch (Exception exception)
            {
                var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
                response.Content = new StringContent(exception.Message);
                return(response);
            }

            return(new HttpResponseMessage(HttpStatusCode.NoContent));
        }
Beispiel #11
0
        private void ShowSuccess( GatewayComponent gatewayComponent, Person person, PaymentInfo paymentInfo, PaymentSchedule schedule, FinancialPaymentDetail paymentDetail, RockContext rockContext )
        {
            tdTransactionCodeReceipt.Description = TransactionCode;
            tdTransactionCodeReceipt.Visible = !string.IsNullOrWhiteSpace( TransactionCode );

            tdScheduleId.Description = ScheduleId;
            tdScheduleId.Visible = !string.IsNullOrWhiteSpace( ScheduleId );

            tdNameReceipt.Description = paymentInfo.FullName;
            tdPhoneReceipt.Description = paymentInfo.Phone;
            tdEmailReceipt.Description = paymentInfo.Email;
            tdAddressReceipt.Description = string.Format( "{0} {1}, {2} {3}", paymentInfo.Street1, paymentInfo.City, paymentInfo.State, paymentInfo.PostalCode );

            rptAccountListReceipt.DataSource = SelectedAccounts.Where( a => a.Amount != 0 );
            rptAccountListReceipt.DataBind();

            tdTotalReceipt.Description = paymentInfo.Amount.ToString( "C" );

            tdPaymentMethodReceipt.Description = paymentInfo.CurrencyTypeValue.Description;

            string acctNumber = paymentInfo.MaskedNumber;
            if ( string.IsNullOrWhiteSpace( acctNumber ) && paymentDetail != null && !string.IsNullOrWhiteSpace( paymentDetail.AccountNumberMasked ) )
            {
                acctNumber = paymentDetail.AccountNumberMasked;
            }
            tdAccountNumberReceipt.Description = acctNumber;
            tdAccountNumberReceipt.Visible = !string.IsNullOrWhiteSpace( acctNumber );

            tdWhenReceipt.Description = schedule != null ? schedule.ToString() : "Today";

            // If there was a transaction code returned and this was not already created from a previous saved account,
            // show the option to save the account.
            if ( !( paymentInfo is ReferencePaymentInfo ) && !string.IsNullOrWhiteSpace( TransactionCode ) && gatewayComponent.SupportsSavedAccount( paymentInfo.CurrencyTypeValue ) )
            {
                cbSaveAccount.Visible = true;
                pnlSaveAccount.Visible = true;
                txtSaveAccount.Visible = true;

                // If current person does not have a login, have them create a username and password
                phCreateLogin.Visible = !new UserLoginService( rockContext ).GetByPersonId( person.Id ).Any();
            }
            else
            {
                pnlSaveAccount.Visible = false;
            }
        }
Beispiel #12
0
        /// <summary>
        /// Maps the contribution.
        /// </summary>
        /// <param name="csvData">The table data.</param>
        private int MapContribution(CSVInstance csvData)
        {
            var lookupContext = new RockContext();

            var currencyTypes          = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE));
            var currencyTypeACH        = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH))).Id;
            var currencyTypeCash       = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH))).Id;
            var currencyTypeCheck      = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK))).Id;
            var currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD))).Id;
            var currencyTypeNonCash    = currencyTypes.DefinedValues.Where(dv => dv.Value.Equals("Non-Cash")).Select(dv => (int?)dv.Id).FirstOrDefault();

            if (currencyTypeNonCash == null)
            {
                var newTenderNonCash = new DefinedValue
                {
                    Value         = "Non-Cash",
                    Description   = "Non-Cash",
                    DefinedTypeId = currencyTypes.Id
                };
                lookupContext.DefinedValues.Add(newTenderNonCash);
                lookupContext.SaveChanges();
                currencyTypeNonCash = newTenderNonCash.Id;
            }

            var creditCardTypes = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE)).DefinedValues;

            var sourceTypeOnsite  = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_ONSITE_COLLECTION), lookupContext).Id;
            var sourceTypeWebsite = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE), lookupContext).Id;
            var sourceTypeKiosk   = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_KIOSK), lookupContext).Id;

            var refundReasons = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON), lookupContext).DefinedValues;

            var accountList = new FinancialAccountService(lookupContext).Queryable().AsNoTracking().ToList();

            int?defaultBatchId = null;

            if (ImportedBatches.ContainsKey(0))
            {
                defaultBatchId = ImportedBatches[0];
            }

            // Look for custom attributes in the Contribution file
            var allFields        = csvData.TableNodes.FirstOrDefault().Children.Select((node, index) => new { node = node, index = index }).ToList();
            var customAttributes = allFields
                                   .Where(f => f.index > ContributionCreditCardType)
                                   .ToDictionary(f => f.index, f => f.node.Name);

            // Get all imported contributions
            var importedContributions = new FinancialTransactionService(lookupContext).Queryable().AsNoTracking()
                                        .Where(c => c.ForeignId != null)
                                        .Select(t => (int)t.ForeignId)
                                        .OrderBy(t => t).ToList();

            // List for batching new contributions
            var newTransactions = new List <FinancialTransaction>();

            var completed = 0;

            ReportProgress(0, $"Verifying contribution import ({importedContributions.Count:N0} already exist).");
            string[] row;
            // Uses a look-ahead enumerator: this call will move to the next record immediately
            while ((row = csvData.Database.FirstOrDefault()) != null)
            {
                var individualIdKey   = row[IndividualID];
                var contributionIdKey = row[ContributionID];
                var contributionId    = contributionIdKey.AsType <int?>();

                if (contributionId != null && !importedContributions.Contains((int)contributionId))
                {
                    var transaction = new FinancialTransaction
                    {
                        CreatedByPersonAliasId  = ImportPersonAliasId,
                        ModifiedByPersonAliasId = ImportPersonAliasId,
                        TransactionTypeValueId  = TransactionTypeContributionId,
                        ForeignKey = contributionId.ToString(),
                        ForeignId  = contributionId
                    };

                    int?giverAliasId = null;
                    var personKeys   = GetPersonKeys(individualIdKey);
                    if (personKeys != null && personKeys.PersonAliasId > 0)
                    {
                        giverAliasId = personKeys.PersonAliasId;
                        transaction.CreatedByPersonAliasId   = giverAliasId;
                        transaction.AuthorizedPersonAliasId  = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }
                    else if (AnonymousGiverAliasId != null && AnonymousGiverAliasId > 0)
                    {
                        giverAliasId = AnonymousGiverAliasId;
                        transaction.AuthorizedPersonAliasId  = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }

                    var summary = row[Memo] as string;
                    if (!string.IsNullOrWhiteSpace(summary))
                    {
                        transaction.Summary = summary;
                    }

                    var batchIdKey = row[ContributionBatchID];
                    var batchId    = batchIdKey.AsType <int?>();
                    if (batchId != null && ImportedBatches.Any(b => b.Key.Equals(batchId)))
                    {
                        transaction.BatchId = ImportedBatches.FirstOrDefault(b => b.Key.Equals(batchId)).Value;
                    }
                    else
                    {
                        // use the default batch for any non-matching transactions
                        transaction.BatchId = defaultBatchId;
                    }

                    var receivedDateKey = row[ReceivedDate];
                    var receivedDate    = receivedDateKey.AsType <DateTime?>();
                    if (receivedDate != null)
                    {
                        transaction.TransactionDateTime = receivedDate;
                        transaction.CreatedDateTime     = receivedDate;
                        transaction.ModifiedDateTime    = ImportDateTime;
                    }

                    var contributionType = row[ContributionTypeName];
                    var creditCardType   = row[ContributionCreditCardType];
                    if (!string.IsNullOrWhiteSpace(contributionType))
                    {
                        // set default source to onsite, exceptions listed below
                        transaction.SourceTypeValueId = sourceTypeOnsite;

                        int?paymentCurrencyTypeId = null, creditCardTypeId = null;

                        if (contributionType.Equals("cash", StringComparison.CurrentCultureIgnoreCase))
                        {
                            paymentCurrencyTypeId = currencyTypeCash;
                        }
                        else if (contributionType.Equals("check", StringComparison.CurrentCultureIgnoreCase))
                        {
                            paymentCurrencyTypeId = currencyTypeCheck;
                        }
                        else if (contributionType.Equals("ach", StringComparison.CurrentCultureIgnoreCase))
                        {
                            paymentCurrencyTypeId         = currencyTypeACH;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else if (contributionType.Equals("credit card", StringComparison.CurrentCultureIgnoreCase))
                        {
                            paymentCurrencyTypeId         = currencyTypeCreditCard;
                            transaction.SourceTypeValueId = sourceTypeWebsite;

                            // Determine CC Type
                            if (!string.IsNullOrWhiteSpace(creditCardType))
                            {
                                creditCardTypeId = creditCardTypes.Where(c => c.Value.StartsWith(creditCardType, StringComparison.CurrentCultureIgnoreCase) ||
                                                                         c.Description.StartsWith(creditCardType, StringComparison.CurrentCultureIgnoreCase))
                                                   .Select(c => c.Id).FirstOrDefault();
                            }
                        }
                        else
                        {
                            paymentCurrencyTypeId = currencyTypeNonCash;
                        }

                        var paymentDetail = new FinancialPaymentDetail
                        {
                            CreatedDateTime         = receivedDate,
                            CreatedByPersonAliasId  = giverAliasId,
                            ModifiedDateTime        = ImportDateTime,
                            ModifiedByPersonAliasId = giverAliasId,
                            CurrencyTypeValueId     = paymentCurrencyTypeId,
                            CreditCardTypeValueId   = creditCardTypeId,
                            ForeignKey = contributionId.ToString(),
                            ForeignId  = contributionId
                        };

                        transaction.FinancialPaymentDetail = paymentDetail;
                    }

                    var transactionCode = row[CheckNumber] as string;
                    // if transaction code provided, put it in the transaction code
                    if (!string.IsNullOrEmpty(transactionCode))
                    {
                        transaction.TransactionCode = transactionCode;

                        // check for SecureGive kiosk transactions
                        if (transactionCode.StartsWith("SG"))
                        {
                            transaction.SourceTypeValueId = sourceTypeKiosk;
                        }
                    }

                    var fundName           = row[FundName] as string;
                    var subFund            = row[SubFundName] as string;
                    var fundGLAccount      = row[FundGLAccount] as string;
                    var subFundGLAccount   = row[SubFundGLAccount] as string;
                    var isFundActiveKey    = row[FundIsActive];
                    var isFundActive       = isFundActiveKey.AsType <bool?>();
                    var isSubFundActiveKey = row[SubFundIsActive];
                    var isSubFundActive    = isSubFundActiveKey.AsType <bool?>();
                    var statedValueKey     = row[StatedValue];
                    var statedValue        = statedValueKey.AsType <decimal?>();
                    var amountKey          = row[Amount];
                    var amount             = amountKey.AsType <decimal?>();
                    if (!string.IsNullOrWhiteSpace(fundName) & amount != null)
                    {
                        int transactionAccountId;
                        var parentAccount = accountList.FirstOrDefault(a => a.Name.Equals(fundName.Truncate(50)));
                        if (parentAccount == null)
                        {
                            parentAccount = AddAccount(lookupContext, fundName, fundGLAccount, null, null, isFundActive, null, null, null, null, "", "", null);
                            accountList.Add(parentAccount);
                        }

                        if (!string.IsNullOrWhiteSpace(subFund))
                        {
                            int?campusFundId = null;
                            // assign a campus if the subfund is a campus fund
                            var campusFund = CampusList.FirstOrDefault(c => subFund.Contains(c.Name) || subFund.Contains(c.ShortCode));
                            if (campusFund != null)
                            {
                                campusFundId = campusFund.Id;
                            }

                            // add info to easily find/assign this fund in the view
                            subFund = $"{fundName} {subFund}";

                            var childAccount = accountList.FirstOrDefault(c => c.Name.Equals(subFund.Truncate(50)) && c.ParentAccountId == parentAccount.Id);
                            if (childAccount == null)
                            {
                                // create a child account with a campusId if it was set
                                childAccount = AddAccount(lookupContext, subFund, subFundGLAccount, campusFundId, parentAccount.Id, isSubFundActive, null, null, null, null, "", "", null);
                                accountList.Add(childAccount);
                            }

                            transactionAccountId = childAccount.Id;
                        }
                        else
                        {
                            transactionAccountId = parentAccount.Id;
                        }

                        if (amount == 0 && statedValue != null && statedValue != 0)
                        {
                            amount = statedValue;
                        }

                        var transactionDetail = new FinancialTransactionDetail
                        {
                            Amount          = (decimal)amount,
                            CreatedDateTime = receivedDate,
                            AccountId       = transactionAccountId
                        };
                        transaction.TransactionDetails.Add(transactionDetail);

                        if (amount < 0)
                        {
                            transaction.RefundDetails = new FinancialTransactionRefund();
                            transaction.RefundDetails.CreatedDateTime     = receivedDate;
                            transaction.RefundDetails.RefundReasonValueId = refundReasons.Where(dv => summary != null && dv.Value.Contains(summary))
                                                                            .Select(dv => (int?)dv.Id).FirstOrDefault();
                            transaction.RefundDetails.RefundReasonSummary = summary;
                        }
                    }

                    newTransactions.Add(transaction);
                    completed++;
                    if (completed % (ReportingNumber * 10) < 1)
                    {
                        ReportProgress(0, $"{completed:N0} contributions imported.");
                    }
                    else if (completed % ReportingNumber < 1)
                    {
                        SaveContributions(newTransactions);
                        newTransactions.Clear();
                        ReportPartialProgress();
                    }
                }
            }

            if (newTransactions.Any())
            {
                SaveContributions(newTransactions);
            }

            ReportProgress(100, $"Finished contribution import: {completed:N0} contributions imported.");
            return(completed);
        }
Beispiel #13
0
        /// <summary>
        /// Maps the contribution.
        /// </summary>
        /// <param name="csvData">The table data.</param>
        private int MapContribution( CSVInstance csvData )
        {
            var lookupContext = new RockContext();
            int transactionEntityTypeId = EntityTypeCache.Read( "Rock.Model.FinancialTransaction" ).Id;
            var transactionTypeContributionId = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ), lookupContext ).Id;

            var currencyTypes = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE ) );
            int currencyTypeACH = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH ) ) ).Id;
            int currencyTypeCash = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH ) ) ).Id;
            int currencyTypeCheck = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK ) ) ).Id;
            int currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) ).Id;
            int? currencyTypeNonCash = currencyTypes.DefinedValues.Where( dv => dv.Value.Equals( "Non-Cash" ) ).Select( dv => ( int? )dv.Id ).FirstOrDefault();
            if ( currencyTypeNonCash == null )
            {
                var newTenderNonCash = new DefinedValue();
                newTenderNonCash.Value = "Non-Cash";
                newTenderNonCash.Description = "Non-Cash";
                newTenderNonCash.DefinedTypeId = currencyTypes.Id;
                lookupContext.DefinedValues.Add( newTenderNonCash );
                lookupContext.SaveChanges();

                currencyTypeNonCash = newTenderNonCash.Id;
            }

            var creditCardTypes = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE ) ).DefinedValues;

            int sourceTypeOnsite = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_ONSITE_COLLECTION ), lookupContext ).Id;
            int sourceTypeWebsite = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE ), lookupContext ).Id;
            int sourceTypeKiosk = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_KIOSK ), lookupContext ).Id;

            var refundReasons = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON ), lookupContext ).DefinedValues;

            var accountList = new FinancialAccountService( lookupContext ).Queryable().AsNoTracking().ToList();

            int? defaultBatchId = null;
            if ( ImportedBatches.ContainsKey( 0 ) )
            {
                defaultBatchId = ImportedBatches[0];
            }

            // Get all imported contributions
            var importedContributions = new FinancialTransactionService( lookupContext ).Queryable().AsNoTracking()
               .Where( c => c.ForeignId != null )
               .ToDictionary( t => ( int )t.ForeignId, t => ( int? )t.Id );

            // List for batching new contributions
            var newTransactions = new List<FinancialTransaction>();

            int completed = 0;
            ReportProgress( 0, string.Format( "Verifying contribution import ({0:N0} already exist).", importedContributions.Count ) );
            string[] row;
            // Uses a look-ahead enumerator: this call will move to the next record immediately
            while ( (row = csvData.Database.FirstOrDefault()) != null )
            {
                string individualIdKey = row[IndividualID];
                int? individualId = individualIdKey.AsType<int?>();
                string contributionIdKey = row[ContributionID];
                int? contributionId = contributionIdKey.AsType<int?>();

                if ( contributionId != null && !importedContributions.ContainsKey( ( int )contributionId ) )
                {
                    var transaction = new FinancialTransaction();
                    transaction.CreatedByPersonAliasId = ImportPersonAliasId;
                    transaction.ModifiedByPersonAliasId = ImportPersonAliasId;
                    transaction.TransactionTypeValueId = transactionTypeContributionId;
                    transaction.ForeignKey = contributionId.ToString();
                    transaction.ForeignId = contributionId;

                    int? giverAliasId = null;
                    var personKeys = GetPersonKeys( individualId );
                    if ( personKeys != null && personKeys.PersonAliasId > 0 )
                    {
                        giverAliasId = personKeys.PersonAliasId;
                        transaction.CreatedByPersonAliasId = giverAliasId;
                        transaction.AuthorizedPersonAliasId = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }
                    else if ( AnonymousGiverAliasId != null && AnonymousGiverAliasId > 0 )
                    {
                        giverAliasId = AnonymousGiverAliasId;
                        transaction.AuthorizedPersonAliasId = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }

                    string summary = row[Memo] as string;
                    if ( !String.IsNullOrWhiteSpace( summary ) )
                    {
                        transaction.Summary = summary;
                    }

                    string batchIdKey = row[ContributionBatchID];
                    int? batchId = batchIdKey.AsType<int?>();
                    if ( batchId != null && ImportedBatches.Any( b => b.Key.Equals( batchId ) ) )
                    {
                        transaction.BatchId = ImportedBatches.FirstOrDefault( b => b.Key.Equals( batchId ) ).Value;
                    }
                    else
                    {
                        // use the default batch for any non-matching transactions
                        transaction.BatchId = defaultBatchId;
                    }

                    string receivedDateKey = row[ReceivedDate];
                    DateTime? receivedDate = receivedDateKey.AsType<DateTime?>();
                    if ( receivedDate != null )
                    {
                        transaction.TransactionDateTime = receivedDate;
                        transaction.CreatedDateTime = receivedDate;
                        transaction.ModifiedDateTime = ImportDateTime;
                    }

                    string contributionType = row[ContributionTypeName].ToStringSafe().ToLower();
                    if ( !String.IsNullOrWhiteSpace( contributionType ) )
                    {
                        // set default source to onsite, exceptions listed below
                        transaction.SourceTypeValueId = sourceTypeOnsite;

                        int? paymentCurrencyTypeId = null, creditCardTypeId = null;

                        if ( contributionType == "cash" )
                        {
                            paymentCurrencyTypeId = currencyTypeCash;
                        }
                        else if ( contributionType == "check" )
                        {
                            paymentCurrencyTypeId = currencyTypeCheck;
                        }
                        else if ( contributionType == "ach" )
                        {
                            paymentCurrencyTypeId = currencyTypeACH;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else if ( contributionType == "credit card" )
                        {
                            paymentCurrencyTypeId = currencyTypeCreditCard;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else
                        {
                            paymentCurrencyTypeId = currencyTypeNonCash;
                        }

                        var paymentDetail = new FinancialPaymentDetail();
                        paymentDetail.CreatedDateTime = receivedDate;
                        paymentDetail.CreatedByPersonAliasId = giverAliasId;
                        paymentDetail.ModifiedDateTime = ImportDateTime;
                        paymentDetail.ModifiedByPersonAliasId = giverAliasId;
                        paymentDetail.CurrencyTypeValueId = paymentCurrencyTypeId;
                        paymentDetail.CreditCardTypeValueId = creditCardTypeId;
                        paymentDetail.ForeignKey = contributionId.ToString();
                        paymentDetail.ForeignId = contributionId;

                        transaction.FinancialPaymentDetail = paymentDetail;
                    }

                    string checkNumber = row[CheckNumber] as string;
                    // if the check number is valid, put it in the transaction code
                    if ( checkNumber.AsType<int?>() != null )
                    {
                        transaction.TransactionCode = checkNumber;
                    }
                    // check for SecureGive kiosk transactions
                    else if ( !string.IsNullOrEmpty( checkNumber ) && checkNumber.StartsWith( "SG" ) )
                    {
                        transaction.SourceTypeValueId = sourceTypeKiosk;
                    }

                    string fundName = row[FundName] as string;
                    string subFund = row[SubFundName] as string;
                    string fundGLAccount = row[FundGLAccount] as string;
                    string subFundGLAccount = row[SubFundGLAccount] as string;
                    string isFundActiveKey = row[FundIsActive];
                    Boolean? isFundActive = isFundActiveKey.AsType<Boolean?>();
                    string isSubFundActiveKey = row[SubFundIsActive];
                    Boolean? isSubFundActive = isSubFundActiveKey.AsType<Boolean?>();
                    string statedValueKey = row[StatedValue];
                    decimal? statedValue = statedValueKey.AsType<decimal?>();
                    string amountKey = row[Amount];
                    decimal? amount = amountKey.AsType<decimal?>();
                    if ( !String.IsNullOrWhiteSpace( fundName ) & amount != null )
                    {
                        int transactionAccountId;
                        var parentAccount = accountList.FirstOrDefault( a => a.Name.Equals( fundName.Truncate( 50 ) ) && a.CampusId == null );
                        if ( parentAccount == null )
                        {
                            parentAccount = AddAccount( lookupContext, fundName, fundGLAccount, null, null, isFundActive );
                            accountList.Add( parentAccount );
                        }

                        if ( !String.IsNullOrWhiteSpace( subFund ) )
                        {
                            int? campusFundId = null;
                            // assign a campus if the subfund is a campus fund
                            var campusFund = CampusList.FirstOrDefault( c => subFund.StartsWith( c.Name ) || subFund.StartsWith( c.ShortCode ) );
                            if ( campusFund != null )
                            {
                                // use full campus name as the subfund
                                subFund = campusFund.Name;
                                campusFundId = campusFund.Id;
                            }

                            // add info to easily find/assign this fund in the view
                            subFund = string.Format( "{0} {1}", subFund, fundName );

                            var childAccount = accountList.FirstOrDefault( c => c.Name.Equals( subFund.Truncate( 50 ) ) && c.ParentAccountId == parentAccount.Id );
                            if ( childAccount == null )
                            {
                                // create a child account with a campusId if it was set
                                childAccount = AddAccount( lookupContext, subFund, subFundGLAccount, campusFundId, parentAccount.Id, isSubFundActive );
                                accountList.Add( childAccount );
                            }

                            transactionAccountId = childAccount.Id;
                        }
                        else
                        {
                            transactionAccountId = parentAccount.Id;
                        }

                        if ( amount == 0 && statedValue != null && statedValue != 0 )
                        {
                            amount = statedValue;
                        }

                        var transactionDetail = new FinancialTransactionDetail();
                        transactionDetail.Amount = ( decimal )amount;
                        transactionDetail.CreatedDateTime = receivedDate;
                        transactionDetail.AccountId = transactionAccountId;
                        transaction.TransactionDetails.Add( transactionDetail );

                        if ( amount < 0 )
                        {
                            transaction.RefundDetails = new FinancialTransactionRefund();
                            transaction.RefundDetails.CreatedDateTime = receivedDate;
                            transaction.RefundDetails.RefundReasonValueId = refundReasons.Where( dv => summary != null && dv.Value.Contains( summary ) )
                                .Select( dv => ( int? )dv.Id ).FirstOrDefault();
                            transaction.RefundDetails.RefundReasonSummary = summary;
                        }
                    }

                    newTransactions.Add( transaction );
                    completed++;
                    if ( completed % (ReportingNumber * 10) < 1 )
                    {
                        ReportProgress( 0, string.Format( "{0:N0} contributions imported.", completed ) );
                    }
                    else if ( completed % ReportingNumber < 1 )
                    {
                        SaveContributions( newTransactions );
                        newTransactions.Clear();
                        ReportPartialProgress();
                    }
                }
            }

            if ( newTransactions.Any() )
            {
                SaveContributions( newTransactions );
            }

            ReportProgress( 100, string.Format( "Finished contribution import: {0:N0} contributions imported.", completed ) );
            return completed;
        }
Beispiel #14
0
        /// <summary>
        /// Gets the payment information.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="person">The person.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="totalAmount">The total amount.</param>
        /// <param name="paymentDetail">The payment detail.</param>
        /// <returns></returns>
        private PaymentInfo GetPaymentInfo(PaymentParameters parameters, Person person, RockContext rockContext, decimal totalAmount, FinancialPaymentDetail paymentDetail)
        {
            PaymentInfo paymentInfo = null;

            if (parameters.AccountType.ToLower() == "credit")
            {
                if (parameters.ExpirationMonth < 1 || parameters.ExpirationMonth > 12)
                {
                    GenerateResponse(HttpStatusCode.BadRequest, "ExpirationMonth is required and must be between 1 and 12 for credit transactions");
                }

                var currentDate = DateTime.Now;
                var maxYear     = currentDate.Year + 30;

                if (parameters.ExpirationYear < currentDate.Year || parameters.ExpirationYear > maxYear)
                {
                    GenerateResponse(HttpStatusCode.BadRequest, string.Format("ExpirationYear is required and must be between {0} and {1} for credit transactions", currentDate.Year, maxYear));
                }

                if (parameters.ExpirationYear <= currentDate.Year && parameters.ExpirationMonth < currentDate.Month)
                {
                    GenerateResponse(HttpStatusCode.BadRequest, "The ExpirationMonth and ExpirationYear combination must not have already elapsed for credit transactions");
                }

                if (string.IsNullOrWhiteSpace(parameters.Street1) ||
                    string.IsNullOrWhiteSpace(parameters.City) ||
                    string.IsNullOrWhiteSpace(parameters.State) ||
                    string.IsNullOrWhiteSpace(parameters.PostalCode))
                {
                    GenerateResponse(HttpStatusCode.BadRequest, "Street1, City, State, and PostalCode are required for credit transactions");
                }

                paymentInfo = new CreditCardPaymentInfo()
                {
                    Number            = parameters.AccountNumber,
                    Code              = parameters.CCV ?? string.Empty,
                    ExpirationDate    = new DateTime(parameters.ExpirationYear, parameters.ExpirationMonth, 1),
                    BillingStreet1    = parameters.Street1 ?? string.Empty,
                    BillingStreet2    = parameters.Street2 ?? string.Empty,
                    BillingCity       = parameters.City ?? string.Empty,
                    BillingState      = parameters.State ?? string.Empty,
                    BillingPostalCode = parameters.PostalCode ?? string.Empty,
                    BillingCountry    = parameters.Country ?? "USA"
                };
            }
            else
            {
                if (string.IsNullOrWhiteSpace(parameters.RoutingNumber))
                {
                    GenerateResponse(HttpStatusCode.BadRequest, "RoutingNumber is required for ACH transactions");
                    return(null);
                }

                paymentInfo = new ACHPaymentInfo()
                {
                    BankRoutingNumber = parameters.RoutingNumber,
                    BankAccountNumber = parameters.AccountNumber,
                    AccountType       = parameters.AccountType.ToLower() == "checking" ? BankAccountType.Checking : BankAccountType.Savings
                };
            }

            paymentInfo.Amount     = totalAmount;
            paymentInfo.FirstName  = parameters.FirstName ?? person.FirstName;
            paymentInfo.LastName   = parameters.LastName ?? person.LastName;
            paymentInfo.Email      = parameters.Email ?? person.Email;
            paymentInfo.Phone      = parameters.PhoneNumber ?? string.Empty;
            paymentInfo.Street1    = parameters.Street1 ?? string.Empty;
            paymentInfo.Street2    = parameters.Street2 ?? string.Empty;
            paymentInfo.City       = parameters.City ?? string.Empty;
            paymentInfo.State      = parameters.State ?? string.Empty;
            paymentInfo.PostalCode = parameters.PostalCode ?? string.Empty;
            paymentInfo.Country    = parameters.Country ?? "USA";

            if (paymentInfo.CreditCardTypeValue != null)
            {
                paymentDetail.CreditCardTypeValueId = paymentInfo.CreditCardTypeValue.Id;
            }

            if (paymentInfo.CurrencyTypeValue != null)
            {
                paymentDetail.CurrencyTypeValueId = paymentInfo.CurrencyTypeValue.Id;
            }

            return(paymentInfo);
        }
Beispiel #15
0
        /// <summary>
        /// Creates the saved account.
        /// </summary>
        /// <param name="parameters">The parameters.</param>
        /// <param name="paymentDetail">The payment detail.</param>
        /// <param name="financialGateway">The financial gateway.</param>
        /// <param name="person">The person.</param>
        /// <param name="rockContext">The rock context.</param>
        /// <returns></returns>
        private FinancialPersonSavedAccount CreateSavedAccount(PaymentParameters parameters, FinancialPaymentDetail paymentDetail, FinancialGateway financialGateway, Person person, RockContext rockContext)
        {
            var lastFour = paymentDetail.AccountNumberMasked.Substring(paymentDetail.AccountNumberMasked.Length - 4);
            var name     = string.Empty;

            if (parameters.AccountType.ToLower() != "credit")
            {
                if (string.IsNullOrWhiteSpace(parameters.RoutingNumber))
                {
                    GenerateResponse(HttpStatusCode.BadRequest, "RoutingNumber is required for ACH transactions");
                    return(null);
                }

                if (string.IsNullOrWhiteSpace(parameters.AccountNumber))
                {
                    GenerateResponse(HttpStatusCode.BadRequest, "AccountNumber is required");
                    return(null);
                }

                name = "Bank card ***" + lastFour;
                var bankAccountService   = new FinancialPersonBankAccountService(rockContext);
                var accountNumberSecured = FinancialPersonBankAccount.EncodeAccountNumber(parameters.RoutingNumber, parameters.AccountNumber);
                var bankAccount          = bankAccountService.Queryable().Where(a =>
                                                                                a.AccountNumberSecured == accountNumberSecured &&
                                                                                a.PersonAliasId == person.PrimaryAliasId.Value).FirstOrDefault();

                if (bankAccount == null)
                {
                    bankAccount = new FinancialPersonBankAccount();
                    bankAccount.PersonAliasId        = person.PrimaryAliasId.Value;
                    bankAccount.AccountNumberMasked  = paymentDetail.AccountNumberMasked;
                    bankAccount.AccountNumberSecured = accountNumberSecured;
                    bankAccountService.Add(bankAccount);
                }
            }
            else
            {
                name = "Credit card ***" + lastFour;
            }

            var savedAccount = new FinancialPersonSavedAccount {
                PersonAliasId      = person.PrimaryAliasId,
                FinancialGatewayId = financialGateway.Id,
                Name = name,
                FinancialPaymentDetailId = paymentDetail.Id
            };

            new FinancialPersonSavedAccountService(rockContext).Add(savedAccount);
            rockContext.SaveChanges();
            return(savedAccount);
        }
Beispiel #16
0
        private void ShowSuccess(GatewayComponent gatewayComponent, Person person, PaymentInfo paymentInfo, PaymentSchedule schedule, FinancialPaymentDetail paymentDetail, RockContext rockContext)
        {
            tdTransactionCodeReceipt.Description = TransactionCode;
            tdTransactionCodeReceipt.Visible     = !string.IsNullOrWhiteSpace(TransactionCode);

            tdScheduleId.Description = ScheduleId.ToString();
            tdScheduleId.Visible     = ScheduleId.HasValue;

            tdNameReceipt.Description    = paymentInfo.FullName;
            tdPhoneReceipt.Description   = paymentInfo.Phone;
            tdEmailReceipt.Description   = paymentInfo.Email;
            tdAddressReceipt.Description = string.Format("{0} {1}, {2} {3}", paymentInfo.Street1, paymentInfo.City, paymentInfo.State, paymentInfo.PostalCode);

            rptAccountListReceipt.DataSource = GetSelectedAccounts().Where(a => a.Amount != 0);
            rptAccountListReceipt.DataBind();

            tdTotalReceipt.Description = paymentInfo.Amount.ToString("C");

            tdPaymentMethodReceipt.Description = paymentInfo.CurrencyTypeValue.Description;

            string acctNumber = paymentInfo.MaskedNumber;

            if (string.IsNullOrWhiteSpace(acctNumber) && paymentDetail != null && !string.IsNullOrWhiteSpace(paymentDetail.AccountNumberMasked))
            {
                acctNumber = paymentDetail.AccountNumberMasked;
            }
            tdAccountNumberReceipt.Description = acctNumber;
            tdAccountNumberReceipt.Visible     = !string.IsNullOrWhiteSpace(acctNumber);

            tdWhenReceipt.Description = schedule != null?schedule.ToString() : "Today";

            pnlConfirmation.Visible = false;
            pnlSuccess.Visible      = true;
        }
Beispiel #17
0
        /// <summary>
        /// Maps the contribution.
        /// </summary>
        /// <param name="tableData">The table data.</param>
        /// <param name="selectedColumns">The selected columns.</param>
        private void MapContribution(IQueryable <Row> tableData, List <string> selectedColumns = null)
        {
            var lookupContext                 = new RockContext();
            int transactionEntityTypeId       = EntityTypeCache.Read("Rock.Model.FinancialTransaction").Id;
            var transactionTypeContributionId = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION), lookupContext).Id;

            var currencyTypes          = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE));
            int currencyTypeACH        = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH))).Id;
            int currencyTypeCash       = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH))).Id;
            int currencyTypeCheck      = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK))).Id;
            int currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD))).Id;
            int?currencyTypeNonCash    = currencyTypes.DefinedValues.Where(dv => dv.Value.Equals("Non-Cash")).Select(dv => (int?)dv.Id).FirstOrDefault();

            if (currencyTypeNonCash == null)
            {
                var newTenderNonCash = new DefinedValue();
                newTenderNonCash.Value         = "Non-Cash";
                newTenderNonCash.Description   = "Non-Cash";
                newTenderNonCash.DefinedTypeId = currencyTypes.Id;
                lookupContext.DefinedValues.Add(newTenderNonCash);
                lookupContext.SaveChanges();

                currencyTypeNonCash = newTenderNonCash.Id;
            }

            var creditCardTypes = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE)).DefinedValues;

            int sourceTypeOnsite  = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_ONSITE_COLLECTION), lookupContext).Id;
            int sourceTypeWebsite = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE), lookupContext).Id;
            int sourceTypeKiosk   = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_KIOSK), lookupContext).Id;

            var refundReasons = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON), lookupContext).DefinedValues;

            var accountList = new FinancialAccountService(lookupContext).Queryable().AsNoTracking().ToList();

            int?defaultBatchId = null;

            if (ImportedBatches.ContainsKey(0))
            {
                defaultBatchId = ImportedBatches[0];
            }

            // Get all imported contributions
            var importedContributions = new FinancialTransactionService(lookupContext).Queryable().AsNoTracking()
                                        .Where(c => c.ForeignId != null)
                                        .ToDictionary(t => (int)t.ForeignId, t => (int?)t.Id);

            // List for batching new contributions
            var newTransactions = new List <FinancialTransaction>();

            int completed  = 0;
            int totalRows  = tableData.Count();
            int percentage = (totalRows - 1) / 100 + 1;

            ReportProgress(0, string.Format("Verifying contribution import ({0:N0} found, {1:N0} already exist).", totalRows, importedContributions.Count));
            foreach (var row in tableData.Where(r => r != null))
            {
                int?individualId   = row["Individual_ID"] as int?;
                int?householdId    = row["Household_ID"] as int?;
                int?contributionId = row["ContributionID"] as int?;

                if (contributionId != null && !importedContributions.ContainsKey((int)contributionId))
                {
                    var transaction = new FinancialTransaction();
                    transaction.CreatedByPersonAliasId  = ImportPersonAliasId;
                    transaction.ModifiedByPersonAliasId = ImportPersonAliasId;
                    transaction.TransactionTypeValueId  = transactionTypeContributionId;
                    transaction.ForeignKey = contributionId.ToString();
                    transaction.ForeignId  = contributionId;

                    int?giverAliasId = null;
                    var personKeys   = GetPersonKeys(individualId, householdId);
                    if (personKeys != null && personKeys.PersonAliasId > 0)
                    {
                        giverAliasId = personKeys.PersonAliasId;
                        transaction.CreatedByPersonAliasId   = giverAliasId;
                        transaction.AuthorizedPersonAliasId  = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }

                    string summary = row["Memo"] as string;
                    if (summary != null)
                    {
                        transaction.Summary = summary;
                    }

                    int?batchId = row["BatchID"] as int?;
                    if (batchId != null && ImportedBatches.Any(b => b.Key.Equals(batchId)))
                    {
                        transaction.BatchId = ImportedBatches.FirstOrDefault(b => b.Key.Equals(batchId)).Value;
                    }
                    else
                    {
                        // use the default batch for any non-matching transactions
                        transaction.BatchId = defaultBatchId;
                    }

                    DateTime?receivedDate = row["Received_Date"] as DateTime?;
                    if (receivedDate != null)
                    {
                        transaction.TransactionDateTime = receivedDate;
                        transaction.CreatedDateTime     = receivedDate;
                        transaction.ModifiedDateTime    = ImportDateTime;
                    }

                    string cardType         = row["Card_Type"] as string;
                    string cardLastFour     = row["Last_Four"] as string;
                    string contributionType = row["Contribution_Type_Name"].ToStringSafe().ToLower();
                    if (contributionType != null)
                    {
                        // set default source to onsite, exceptions listed below
                        transaction.SourceTypeValueId = sourceTypeOnsite;

                        int?paymentCurrencyTypeId = null, creditCardTypeId = null;

                        if (contributionType == "cash")
                        {
                            paymentCurrencyTypeId = currencyTypeCash;
                        }
                        else if (contributionType == "check")
                        {
                            paymentCurrencyTypeId = currencyTypeCheck;
                        }
                        else if (contributionType == "ach")
                        {
                            paymentCurrencyTypeId         = currencyTypeACH;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else if (contributionType == "credit card")
                        {
                            paymentCurrencyTypeId         = currencyTypeCreditCard;
                            transaction.SourceTypeValueId = sourceTypeWebsite;

                            if (cardType != null)
                            {
                                creditCardTypeId = creditCardTypes.Where(t => t.Value.Equals(cardType)).Select(t => (int?)t.Id).FirstOrDefault();
                            }
                        }
                        else
                        {
                            paymentCurrencyTypeId = currencyTypeNonCash;
                        }

                        var paymentDetail = new FinancialPaymentDetail();
                        paymentDetail.CreatedDateTime         = receivedDate;
                        paymentDetail.CreatedByPersonAliasId  = giverAliasId;
                        paymentDetail.ModifiedDateTime        = ImportDateTime;
                        paymentDetail.ModifiedByPersonAliasId = giverAliasId;
                        paymentDetail.CurrencyTypeValueId     = paymentCurrencyTypeId;
                        paymentDetail.CreditCardTypeValueId   = creditCardTypeId;
                        paymentDetail.AccountNumberMasked     = cardLastFour;
                        paymentDetail.ForeignKey = contributionId.ToString();
                        paymentDetail.ForeignId  = contributionId;

                        transaction.FinancialPaymentDetail = paymentDetail;
                    }

                    string checkNumber = row["Check_Number"] as string;
                    // if the check number is valid, put it in the transaction code
                    if (checkNumber.AsType <int?>() != null)
                    {
                        transaction.TransactionCode = checkNumber;
                    }
                    // check for SecureGive kiosk transactions
                    else if (!string.IsNullOrEmpty(checkNumber) && checkNumber.StartsWith("SG"))
                    {
                        transaction.SourceTypeValueId = sourceTypeKiosk;
                    }

                    string  fundName         = row["Fund_Name"] as string;
                    string  subFund          = row["Sub_Fund_Name"] as string;
                    string  fundGLAccount    = row["Fund_GL_Account"] as string;
                    string  subFundGLAccount = row["Sub_Fund_GL_Account"] as string;
                    Boolean?isFundActive     = row["Fund_Is_active"] as Boolean?;
                    decimal?statedValue      = row["Stated_Value"] as decimal?;
                    decimal?amount           = row["Amount"] as decimal?;
                    if (fundName != null & amount != null)
                    {
                        int transactionAccountId;
                        var parentAccount = accountList.FirstOrDefault(a => a.Name.Equals(fundName) && a.CampusId == null);
                        if (parentAccount == null)
                        {
                            parentAccount = AddAccount(lookupContext, fundName, fundGLAccount, null, null, isFundActive);
                            accountList.Add(parentAccount);
                        }

                        if (subFund != null)
                        {
                            int?campusFundId = null;
                            // assign a campus if the subfund is a campus fund
                            var campusFund = CampusList.FirstOrDefault(c => subFund.StartsWith(c.Name) || subFund.StartsWith(c.ShortCode));
                            if (campusFund != null)
                            {
                                // use full campus name as the subfund
                                subFund      = campusFund.Name;
                                campusFundId = campusFund.Id;
                            }

                            // add info to easily find/assign this fund in the view
                            subFund = string.Format("{0} {1}", subFund, fundName);

                            var childAccount = accountList.FirstOrDefault(c => c.Name.Equals(subFund) && c.ParentAccountId == parentAccount.Id);
                            if (childAccount == null)
                            {
                                // create a child account with a campusId if it was set
                                childAccount = AddAccount(lookupContext, subFund, subFundGLAccount, campusFundId, parentAccount.Id, isFundActive);
                                accountList.Add(childAccount);
                            }

                            transactionAccountId = childAccount.Id;
                        }
                        else
                        {
                            transactionAccountId = parentAccount.Id;
                        }

                        if (amount == 0 && statedValue != null && statedValue != 0)
                        {
                            amount = statedValue;
                        }

                        var transactionDetail = new FinancialTransactionDetail();
                        transactionDetail.Amount          = (decimal)amount;
                        transactionDetail.CreatedDateTime = receivedDate;
                        transactionDetail.AccountId       = transactionAccountId;
                        transaction.TransactionDetails.Add(transactionDetail);

                        if (amount < 0)
                        {
                            transaction.RefundDetails = new FinancialTransactionRefund();
                            transaction.RefundDetails.CreatedDateTime     = receivedDate;
                            transaction.RefundDetails.RefundReasonValueId = refundReasons.Where(dv => summary != null && dv.Value.Contains(summary))
                                                                            .Select(dv => (int?)dv.Id).FirstOrDefault();
                            transaction.RefundDetails.RefundReasonSummary = summary;
                        }
                    }

                    newTransactions.Add(transaction);
                    completed++;
                    if (completed % percentage < 1)
                    {
                        int percentComplete = completed / percentage;
                        ReportProgress(percentComplete, string.Format("{0:N0} contributions imported ({1}% complete).", completed, percentComplete));
                    }
                    else if (completed % ReportingNumber < 1)
                    {
                        SaveContributions(newTransactions);
                        newTransactions.Clear();
                        ReportPartialProgress();
                    }
                }
            }

            if (newTransactions.Any())
            {
                SaveContributions(newTransactions);
            }

            ReportProgress(100, string.Format("Finished contribution import: {0:N0} contributions imported.", completed));
        }
Beispiel #18
0
        /// <summary>
        /// Maps the contribution.
        /// </summary>
        /// <param name="csvData">The table data.</param>
        private int MapContribution(CSVInstance csvData)
        {
            var lookupContext                 = new RockContext();
            int transactionEntityTypeId       = EntityTypeCache.Read("Rock.Model.FinancialTransaction").Id;
            var transactionTypeContributionId = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION), lookupContext).Id;

            var currencyTypes          = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE));
            int currencyTypeACH        = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH))).Id;
            int currencyTypeCash       = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH))).Id;
            int currencyTypeCheck      = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK))).Id;
            int currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD))).Id;
            int?currencyTypeNonCash    = currencyTypes.DefinedValues.Where(dv => dv.Value.Equals("Non-Cash")).Select(dv => (int?)dv.Id).FirstOrDefault();

            if (currencyTypeNonCash == null)
            {
                var newTenderNonCash = new DefinedValue();
                newTenderNonCash.Value         = "Non-Cash";
                newTenderNonCash.Description   = "Non-Cash";
                newTenderNonCash.DefinedTypeId = currencyTypes.Id;
                lookupContext.DefinedValues.Add(newTenderNonCash);
                lookupContext.SaveChanges();

                currencyTypeNonCash = newTenderNonCash.Id;
            }

            var creditCardTypes = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE)).DefinedValues;

            int sourceTypeOnsite  = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_ONSITE_COLLECTION), lookupContext).Id;
            int sourceTypeWebsite = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE), lookupContext).Id;
            int sourceTypeKiosk   = DefinedValueCache.Read(new Guid(Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_KIOSK), lookupContext).Id;

            var refundReasons = DefinedTypeCache.Read(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON), lookupContext).DefinedValues;

            var accountList = new FinancialAccountService(lookupContext).Queryable().AsNoTracking().ToList();

            int?defaultBatchId = null;

            if (ImportedBatches.ContainsKey(0))
            {
                defaultBatchId = ImportedBatches[0];
            }

            // Get all imported contributions
            var importedContributions = new FinancialTransactionService(lookupContext).Queryable().AsNoTracking()
                                        .Where(c => c.ForeignId != null)
                                        .ToDictionary(t => (int)t.ForeignId, t => (int?)t.Id);

            // List for batching new contributions
            var newTransactions = new List <FinancialTransaction>();

            int completed = 0;

            ReportProgress(0, string.Format("Verifying contribution import ({0:N0} already exist).", importedContributions.Count));
            string[] row;
            // Uses a look-ahead enumerator: this call will move to the next record immediately
            while ((row = csvData.Database.FirstOrDefault()) != null)
            {
                string individualIdKey   = row[IndividualID];
                int?   individualId      = individualIdKey.AsType <int?>();
                string contributionIdKey = row[ContributionID];
                int?   contributionId    = contributionIdKey.AsType <int?>();

                if (contributionId != null && !importedContributions.ContainsKey((int)contributionId))
                {
                    var transaction = new FinancialTransaction();
                    transaction.CreatedByPersonAliasId  = ImportPersonAliasId;
                    transaction.ModifiedByPersonAliasId = ImportPersonAliasId;
                    transaction.TransactionTypeValueId  = transactionTypeContributionId;
                    transaction.ForeignKey = contributionId.ToString();
                    transaction.ForeignId  = contributionId;

                    int?giverAliasId = null;
                    var personKeys   = GetPersonKeys(individualId);
                    if (personKeys != null && personKeys.PersonAliasId > 0)
                    {
                        giverAliasId = personKeys.PersonAliasId;
                        transaction.CreatedByPersonAliasId   = giverAliasId;
                        transaction.AuthorizedPersonAliasId  = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }

                    string summary = row[Memo] as string;
                    if (summary != null)
                    {
                        transaction.Summary = summary;
                    }

                    string batchIdKey = row[ContributionBatchID];
                    int?   batchId    = batchIdKey.AsType <int?>();
                    if (batchId != null && ImportedBatches.Any(b => b.Key.Equals(batchId)))
                    {
                        transaction.BatchId = ImportedBatches.FirstOrDefault(b => b.Key.Equals(batchId)).Value;
                    }
                    else
                    {
                        // use the default batch for any non-matching transactions
                        transaction.BatchId = defaultBatchId;
                    }

                    string   receivedDateKey = row[ReceivedDate];
                    DateTime?receivedDate    = receivedDateKey.AsType <DateTime?>();
                    if (receivedDate != null)
                    {
                        transaction.TransactionDateTime = receivedDate;
                        transaction.CreatedDateTime     = receivedDate;
                        transaction.ModifiedDateTime    = ImportDateTime;
                    }

                    string contributionType = row[ContributionTypeName].ToStringSafe().ToLower();
                    if (contributionType != null)
                    {
                        // set default source to onsite, exceptions listed below
                        transaction.SourceTypeValueId = sourceTypeOnsite;

                        int?paymentCurrencyTypeId = null, creditCardTypeId = null;

                        if (contributionType == "cash")
                        {
                            paymentCurrencyTypeId = currencyTypeCash;
                        }
                        else if (contributionType == "check")
                        {
                            paymentCurrencyTypeId = currencyTypeCheck;
                        }
                        else if (contributionType == "ach")
                        {
                            paymentCurrencyTypeId         = currencyTypeACH;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else if (contributionType == "credit card")
                        {
                            paymentCurrencyTypeId         = currencyTypeCreditCard;
                            transaction.SourceTypeValueId = sourceTypeWebsite;
                        }
                        else
                        {
                            paymentCurrencyTypeId = currencyTypeNonCash;
                        }

                        var paymentDetail = new FinancialPaymentDetail();
                        paymentDetail.CreatedDateTime         = receivedDate;
                        paymentDetail.CreatedByPersonAliasId  = giverAliasId;
                        paymentDetail.ModifiedDateTime        = ImportDateTime;
                        paymentDetail.ModifiedByPersonAliasId = giverAliasId;
                        paymentDetail.CurrencyTypeValueId     = paymentCurrencyTypeId;
                        paymentDetail.CreditCardTypeValueId   = creditCardTypeId;
                        paymentDetail.ForeignKey = contributionId.ToString();
                        paymentDetail.ForeignId  = contributionId;

                        transaction.FinancialPaymentDetail = paymentDetail;
                    }

                    string checkNumber = row[CheckNumber] as string;
                    // if the check number is valid, put it in the transaction code
                    if (checkNumber.AsType <int?>() != null)
                    {
                        transaction.TransactionCode = checkNumber;
                    }
                    // check for SecureGive kiosk transactions
                    else if (!string.IsNullOrEmpty(checkNumber) && checkNumber.StartsWith("SG"))
                    {
                        transaction.SourceTypeValueId = sourceTypeKiosk;
                    }

                    string  fundName         = row[FundName] as string;
                    string  subFund          = row[SubFundName] as string;
                    string  fundGLAccount    = row[FundGLAccount] as string;
                    string  subFundGLAccount = row[SubFundGLAccount] as string;
                    string  isFundActiveKey  = row[FundIsActive];
                    Boolean?isFundActive     = isFundActiveKey.AsType <Boolean?>();
                    string  statedValueKey   = row[StatedValue];
                    decimal?statedValue      = statedValueKey.AsType <decimal?>();
                    string  amountKey        = row[Amount];
                    decimal?amount           = amountKey.AsType <decimal?>();
                    if (fundName != null & amount != null)
                    {
                        int transactionAccountId;
                        var parentAccount = accountList.FirstOrDefault(a => a.Name.Equals(fundName) && a.CampusId == null);
                        if (parentAccount == null)
                        {
                            parentAccount = AddAccount(lookupContext, fundName, fundGLAccount, null, null, isFundActive);
                            accountList.Add(parentAccount);
                        }

                        if (!String.IsNullOrWhiteSpace(subFund))
                        {
                            int?campusFundId = null;
                            // assign a campus if the subfund is a campus fund
                            var campusFund = CampusList.FirstOrDefault(c => subFund.StartsWith(c.Name) || subFund.StartsWith(c.ShortCode));
                            if (campusFund != null)
                            {
                                // use full campus name as the subfund
                                subFund      = campusFund.Name;
                                campusFundId = campusFund.Id;
                            }

                            // add info to easily find/assign this fund in the view
                            subFund = string.Format("{0} {1}", subFund, fundName);

                            var childAccount = accountList.FirstOrDefault(c => c.Name.Equals(subFund) && c.ParentAccountId == parentAccount.Id);
                            if (childAccount == null)
                            {
                                // create a child account with a campusId if it was set
                                childAccount = AddAccount(lookupContext, subFund, subFundGLAccount, campusFundId, parentAccount.Id, isFundActive);
                                accountList.Add(childAccount);
                            }

                            transactionAccountId = childAccount.Id;
                        }
                        else
                        {
                            transactionAccountId = parentAccount.Id;
                        }

                        if (amount == 0 && statedValue != null && statedValue != 0)
                        {
                            amount = statedValue;
                        }

                        var transactionDetail = new FinancialTransactionDetail();
                        transactionDetail.Amount          = (decimal)amount;
                        transactionDetail.CreatedDateTime = receivedDate;
                        transactionDetail.AccountId       = transactionAccountId;
                        transaction.TransactionDetails.Add(transactionDetail);

                        if (amount < 0)
                        {
                            transaction.RefundDetails = new FinancialTransactionRefund();
                            transaction.RefundDetails.CreatedDateTime     = receivedDate;
                            transaction.RefundDetails.RefundReasonValueId = refundReasons.Where(dv => summary != null && dv.Value.Contains(summary))
                                                                            .Select(dv => (int?)dv.Id).FirstOrDefault();
                            transaction.RefundDetails.RefundReasonSummary = summary;
                        }
                    }

                    newTransactions.Add(transaction);
                    completed++;
                    if (completed % (ReportingNumber * 10) < 1)
                    {
                        ReportProgress(0, string.Format("{0:N0} contributions imported.", completed));
                    }
                    else if (completed % ReportingNumber < 1)
                    {
                        SaveContributions(newTransactions);
                        newTransactions.Clear();
                        ReportPartialProgress();
                    }
                }
            }

            if (newTransactions.Any())
            {
                SaveContributions(newTransactions);
            }

            ReportProgress(100, string.Format("Finished contribution import: {0:N0} contributions imported.", completed));
            return(completed);
        }
Beispiel #19
0
        /// <summary>
        /// Maps the contribution.
        /// </summary>
        /// <param name="tableData">The table data.</param>
        /// <param name="totalRows">The total rows.</param>
        private void MapContribution(IQueryable <Row> tableData, long totalRows = 0)
        {
            var lookupContext = new RockContext();

            var transactionTypeContributionId = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid(), lookupContext).Id;

            var currencyTypes          = DefinedTypeCache.Get(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE));
            var currencyTypeACH        = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH))).Id;
            var currencyTypeCash       = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH))).Id;
            var currencyTypeCheck      = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK))).Id;
            var currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault(dv => dv.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD))).Id;
            var currencyTypeNonCash    = currencyTypes.DefinedValues.Where(dv => dv.Value.Equals("Non-Cash")).Select(dv => ( int? )dv.Id).FirstOrDefault();

            if (currencyTypeNonCash == null)
            {
                var newTenderNonCash = new DefinedValue
                {
                    Value         = "Non-Cash",
                    Description   = "Non-Cash",
                    DefinedTypeId = currencyTypes.Id
                };

                lookupContext.DefinedValues.Add(newTenderNonCash);
                lookupContext.SaveChanges();

                currencyTypeNonCash = newTenderNonCash.Id;
            }

            var creditCardTypes = DefinedTypeCache.Get(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE)).DefinedValues;

            var refundReasons = DefinedTypeCache.Get(new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON), lookupContext).DefinedValues;

            var accountList = new FinancialAccountService(lookupContext).Queryable().AsNoTracking().ToList();

            int?defaultBatchId = null;

            if (ImportedBatches.ContainsKey(0))
            {
                defaultBatchId = ImportedBatches[0];
            }

            // Get all imported contributions
            var importedContributions = new FinancialTransactionService(lookupContext).Queryable().AsNoTracking()
                                        .Where(c => c.ForeignId != null)
                                        .ToDictionary(t => ( int )t.ForeignId, t => ( int? )t.Id);

            // List for batching new contributions
            var newTransactions = new List <FinancialTransaction>();

            if (totalRows == 0)
            {
                totalRows = tableData.Count();
            }

            var completedItems = 0;
            var percentage     = (totalRows - 1) / 100 + 1;

            ReportProgress(0, $"Verifying contribution import ({totalRows:N0} found, {importedContributions.Count:N0} already exist).");
            foreach (var row in tableData.Where(r => r != null))
            {
                var individualId   = row["Individual_ID"] as int?;
                var householdId    = row["Household_ID"] as int?;
                var contributionId = row["ContributionID"] as int?;

                if (contributionId.HasValue && !importedContributions.ContainsKey(( int )contributionId))
                {
                    var transaction = new FinancialTransaction
                    {
                        CreatedByPersonAliasId  = ImportPersonAliasId,
                        ModifiedByPersonAliasId = ImportPersonAliasId,
                        TransactionTypeValueId  = transactionTypeContributionId,
                        ForeignKey = contributionId.ToString(),
                        ForeignId  = contributionId
                    };

                    int?giverAliasId = null;
                    var personKeys   = GetPersonKeys(individualId, householdId);
                    if (personKeys != null && personKeys.PersonAliasId > 0)
                    {
                        giverAliasId = personKeys.PersonAliasId;
                        transaction.CreatedByPersonAliasId   = giverAliasId;
                        transaction.AuthorizedPersonAliasId  = giverAliasId;
                        transaction.ProcessedByPersonAliasId = giverAliasId;
                    }

                    var summary = row["Memo"] as string;
                    if (!string.IsNullOrWhiteSpace(summary))
                    {
                        transaction.Summary = summary;
                    }

                    var batchId = row["BatchID"] as int?;
                    if (batchId.HasValue && ImportedBatches.Any(b => b.Key.Equals(batchId)))
                    {
                        transaction.BatchId = ImportedBatches.FirstOrDefault(b => b.Key.Equals(batchId)).Value;
                    }
                    else
                    {
                        // use the default batch for any non-matching transactions
                        transaction.BatchId = defaultBatchId;
                    }

                    var receivedDate = row["Received_Date"] as DateTime?;
                    if (receivedDate.HasValue)
                    {
                        transaction.TransactionDateTime = receivedDate;
                        transaction.CreatedDateTime     = receivedDate;
                        transaction.ModifiedDateTime    = ImportDateTime;
                    }

                    var contributionFields = row.Columns.Select(c => c.Name).ToList();
                    var cardType           = contributionFields.Contains("Card_Type") ? row["Card_Type"] as string : string.Empty;
                    var cardLastFour       = contributionFields.Contains("Last_Four") ? row["Last_Four"] as string : string.Empty;
                    var contributionType   = contributionFields.Contains("Contribution_Type_Name") ? row["Contribution_Type_Name"] as string : string.Empty;

                    if (!string.IsNullOrWhiteSpace(contributionType))
                    {
                        // set default source to onsite, exceptions listed below
                        transaction.SourceTypeValueId = TransactionSourceTypeOnsiteId;

                        int?paymentCurrencyTypeId = null, creditCardTypeId = null;
                        switch (contributionType.ToLower())
                        {
                        case "cash":
                            paymentCurrencyTypeId = currencyTypeCash;
                            break;

                        case "check":
                            paymentCurrencyTypeId = currencyTypeCheck;
                            break;

                        case "ach":
                            paymentCurrencyTypeId         = currencyTypeACH;
                            transaction.SourceTypeValueId = TransactionSourceTypeWebsiteId;
                            break;

                        case "credit card":
                            paymentCurrencyTypeId         = currencyTypeCreditCard;
                            transaction.SourceTypeValueId = TransactionSourceTypeWebsiteId;

                            if (!string.IsNullOrWhiteSpace(cardType))
                            {
                                creditCardTypeId = creditCardTypes.Where(t => t.Value.Equals(cardType, StringComparison.OrdinalIgnoreCase))
                                                   .Select(t => ( int? )t.Id).FirstOrDefault();
                            }
                            break;

                        default:
                            paymentCurrencyTypeId = currencyTypeNonCash;
                            break;
                        }

                        var paymentDetail = new FinancialPaymentDetail
                        {
                            CreatedDateTime         = receivedDate,
                            CreatedByPersonAliasId  = giverAliasId,
                            ModifiedDateTime        = ImportDateTime,
                            ModifiedByPersonAliasId = giverAliasId,
                            CurrencyTypeValueId     = paymentCurrencyTypeId,
                            CreditCardTypeValueId   = creditCardTypeId,
                            AccountNumberMasked     = cardLastFour,
                            ForeignKey = contributionId.ToString(),
                            ForeignId  = contributionId
                        };

                        transaction.FinancialPaymentDetail = paymentDetail;
                    }

                    var checkNumber = row["Check_Number"] as string;
                    // if the check number is valid, put it in the transaction code
                    if (checkNumber.AsType <int?>().HasValue)
                    {
                        transaction.TransactionCode = checkNumber;
                    }
                    // check for SecureGive kiosk transactions
                    else if (!string.IsNullOrWhiteSpace(checkNumber) && checkNumber.StartsWith("SG"))
                    {
                        transaction.SourceTypeValueId = TransactionSourceTypeKioskId;
                    }

                    var fundName         = contributionFields.Contains("Fund_Name") ? row["Fund_Name"] as string : string.Empty;
                    var fundType         = contributionFields.Contains("Fund_type") ? row["Fund_type"] as string : string.Empty;
                    var subFund          = contributionFields.Contains("Sub_Fund_Name") ? row["Sub_Fund_Name"] as string : string.Empty;
                    var fundGLAccount    = contributionFields.Contains("Fund_GL_Account") ? row["Fund_GL_Account"] as string : string.Empty;
                    var subFundGLAccount = contributionFields.Contains("Sub_Fund_GL_Account") ? row["Sub_Fund_GL_Account"] as string : string.Empty;
                    var isFundActive     = contributionFields.Contains("Fund_Is_active") ? row["Fund_Is_active"] as string : null;
                    var statedValue      = row["Stated_Value"] as decimal?;
                    var amount           = row["Amount"] as decimal?;
                    if (!string.IsNullOrWhiteSpace(fundName) && amount.HasValue)
                    {
                        int transactionAccountId;
                        var parentAccount = accountList.FirstOrDefault(a => !a.CampusId.HasValue && a.Name.Equals(fundName.Truncate(50), StringComparison.OrdinalIgnoreCase));
                        if (parentAccount == null)
                        {
                            int?accountTypeDefinedTypeId = null;
                            if (!string.IsNullOrWhiteSpace(fundType))
                            {
                                accountTypeDefinedTypeId = LoadAccountTypeDefinedValue(lookupContext, fundType);
                            }
                            parentAccount = AddFinancialAccount(lookupContext, fundName, $"{fundName} imported {ImportDateTime}", fundGLAccount, null, null, isFundActive.AsBooleanOrNull(), receivedDate, fundName.RemoveSpecialCharacters(), accountTypeValueId: accountTypeDefinedTypeId);
                            accountList.Add(parentAccount);
                        }

                        if (!string.IsNullOrWhiteSpace(subFund))
                        {
                            int?campusFundId = null;
                            // assign a campus if the subfund is a campus fund
                            var campusFund = CampusList.FirstOrDefault(c => subFund.StartsWith(c.Name, StringComparison.OrdinalIgnoreCase) || subFund.StartsWith(c.ShortCode, StringComparison.OrdinalIgnoreCase));
                            if (campusFund != null)
                            {
                                // use full campus name as the subfund
                                subFund      = campusFund.Name;
                                campusFundId = campusFund.Id;
                            }

                            // add info to easily find/assign this fund in the view
                            subFund = $"{subFund} {fundName}";

                            var childAccount = accountList.FirstOrDefault(c => c.ParentAccountId == parentAccount.Id && c.Name.Equals(subFund.Truncate(50), StringComparison.OrdinalIgnoreCase));
                            if (childAccount == null)
                            {
                                // create a child account with a campusId if it was set
                                childAccount = AddFinancialAccount(lookupContext, subFund, $"{subFund} imported {ImportDateTime}", subFundGLAccount, campusFundId, parentAccount.Id, isFundActive.AsBooleanOrNull(), receivedDate, subFund.RemoveSpecialCharacters(), accountTypeValueId: parentAccount.AccountTypeValueId);
                                accountList.Add(childAccount);
                            }

                            transactionAccountId = childAccount.Id;
                        }
                        else
                        {
                            transactionAccountId = parentAccount.Id;
                        }

                        if (amount == 0 && statedValue.HasValue && statedValue != 0)
                        {
                            amount = statedValue;
                        }

                        var transactionDetail = new FinancialTransactionDetail
                        {
                            Amount          = ( decimal )amount,
                            CreatedDateTime = receivedDate,
                            AccountId       = transactionAccountId
                        };

                        transaction.TransactionDetails.Add(transactionDetail);

                        if (amount < 0)
                        {
                            transaction.RefundDetails = new FinancialTransactionRefund();
                            transaction.RefundDetails.CreatedDateTime     = receivedDate;
                            transaction.RefundDetails.RefundReasonValueId = refundReasons.Where(dv => summary != null && dv.Value.Contains(summary))
                                                                            .Select(dv => ( int? )dv.Id).FirstOrDefault();
                            transaction.RefundDetails.RefundReasonSummary = summary;
                        }
                    }

                    newTransactions.Add(transaction);
                    completedItems++;
                    if (completedItems % percentage < 1)
                    {
                        var percentComplete = completedItems / percentage;
                        ReportProgress(percentComplete, $"{completedItems:N0} contributions imported ({percentComplete}% complete).");
                    }

                    if (completedItems % ReportingNumber < 1)
                    {
                        SaveContributions(newTransactions);
                        newTransactions.Clear();
                        ReportPartialProgress();
                    }
                }
            }

            if (newTransactions.Any())
            {
                SaveContributions(newTransactions);
            }

            ReportProgress(100, $"Finished contribution import: {completedItems:N0} contributions imported.");
        }
Beispiel #20
0
        public HttpResponseMessage ScheduleGiving([FromBody] ScheduleParameters scheduleParameters)
        {
            var rockContext = new RockContext();

            try
            {
                rockContext.WrapTransaction(() =>
                {
                    var person = GetExistingPerson(scheduleParameters.PersonId, rockContext);

                    if (person == null)
                    {
                        GenerateResponse(HttpStatusCode.BadRequest, "An existing person is required to schedule giving");
                    }

                    var totalAmount      = CalculateTotalAmount(scheduleParameters, rockContext);
                    var paymentSchedule  = GetPaymentSchedule(scheduleParameters, person);
                    var gatewayComponent = GatewayContainer.GetComponent(gatewayName);

                    if (gatewayComponent == null)
                    {
                        GenerateResponse(HttpStatusCode.InternalServerError, "There was a problem creating the gateway component");
                    }

                    var financialGateway = new FinancialGatewayService(rockContext).Queryable().FirstOrDefault(g => g.EntityTypeId == gatewayComponent.EntityType.Id);

                    if (financialGateway == null)
                    {
                        GenerateResponse(HttpStatusCode.InternalServerError, "There was a problem creating the financial gateway");
                    }

                    var savedAccount = GetExistingSavedAccount(scheduleParameters, person, rockContext);
                    FinancialPaymentDetail paymentDetail = null;
                    PaymentInfo paymentInfo = null;
                    int?locationId          = null;

                    if (savedAccount == null)
                    {
                        locationId    = CreateLocation(scheduleParameters, rockContext);
                        paymentDetail = CreatePaymentDetail(scheduleParameters, person, locationId.Value, rockContext);
                        savedAccount  = CreateSavedAccount(scheduleParameters, paymentDetail, financialGateway, person, rockContext);
                        paymentInfo   = GetPaymentInfo(scheduleParameters, person, rockContext, totalAmount.Value, paymentDetail);
                    }
                    else
                    {
                        paymentDetail = savedAccount.FinancialPaymentDetail;
                        locationId    = paymentDetail.BillingLocationId;
                        paymentInfo   = savedAccount.GetReferencePayment();
                        UpdatePaymentInfoForSavedAccount(scheduleParameters, paymentInfo, person, rockContext, paymentDetail.BillingLocationId.Value, totalAmount.Value);
                    }

                    SaveLocationToFamilyIfNone(person, locationId.Value, rockContext);
                    string errorMessage;
                    var schedule = gatewayComponent.AddScheduledPayment(financialGateway, paymentSchedule, paymentInfo, out errorMessage);

                    if (schedule == null || !string.IsNullOrWhiteSpace(errorMessage))
                    {
                        GenerateResponse(HttpStatusCode.InternalServerError, errorMessage ?? "The gateway had a problem and/or did not create a transaction as expected");
                    }

                    schedule.TransactionFrequencyValueId = paymentSchedule.TransactionFrequencyValue.Id;

                    if (person.PrimaryAliasId.HasValue)
                    {
                        schedule.AuthorizedPersonAliasId = person.PrimaryAliasId.Value;
                    }

                    schedule.FinancialPaymentDetail = paymentDetail;
                    schedule.FinancialPaymentDetail.CurrencyTypeValueId = paymentInfo.CurrencyTypeValue.Id;

                    if (paymentInfo.CreditCardTypeValue != null)
                    {
                        schedule.FinancialPaymentDetail.CreditCardTypeValueId = paymentInfo.CreditCardTypeValue.Id;
                    }

                    foreach (var accountAmount in scheduleParameters.AmountDetails)
                    {
                        schedule.ScheduledTransactionDetails.Add(new FinancialScheduledTransactionDetail()
                        {
                            Amount    = accountAmount.Amount,
                            AccountId = accountAmount.TargetAccountId
                        });
                    }

                    new FinancialScheduledTransactionService(rockContext).Add(schedule);
                    rockContext.SaveChanges();
                });
            }
            catch (HttpResponseException exception)
            {
                return(exception.Response);
            }
            catch (Exception exception)
            {
                var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
                response.Content = new StringContent(exception.Message);
                return(response);
            }

            return(new HttpResponseMessage(HttpStatusCode.NoContent));
        }