protected void Page_Load (object sender, EventArgs e)
    {
        _transaction = GetTransaction();

        if (!_authority.HasPermission(Permission.CanSeeEconomyTransactions, _transaction.OrganizationId, -1, Authorization.Flag.ExactOrganization))
            throw new UnauthorizedAccessException("Access Denied");


        if (!Page.IsPostBack)
        {
            // Populate all data

            this.DatePicker.DateInput.Culture = new CultureInfo("sv-SE");
            this.DatePicker.SelectedDate = _transaction.DateTime;
            this.TextDescription.Text = _transaction.Description;
            this.TextDescription.Style.Add(HtmlTextWriterStyle.Width, "100%");

            PopulateGrid();
            PopulateEvents();

            IHasIdentity dependency = _transaction.Dependency;
        }

        Documents documents = _transaction.Documents;

        Page.Title = "Auditing Transaction #" + _transaction.Identity.ToString();
    }
        public static void MatchTransactionOpenPayout(int transactionId, int payoutId)
        {
            if (transactionId == 0 || payoutId == 0)
            {
                return;
            }

            AuthenticationData authData = GetAuthenticationDataAndCulture();

            if (
                !authData.Authority.HasAccess(new Access(authData.CurrentOrganization,
                                                         AccessAspect.BookkeepingDetails)))
            {
                throw new UnauthorizedAccessException();
            }

            FinancialTransaction transaction = FinancialTransaction.FromIdentity(transactionId);
            Payout payout = Payout.FromIdentity(payoutId);

            if (transaction.OrganizationId != authData.CurrentOrganization.Identity || payout.OrganizationId != authData.CurrentOrganization.Identity)
            {
                throw new UnauthorizedAccessException();
            }

            Int64 transactionCents = transaction.Rows.AmountCentsTotal;
            Int64 payoutCents      = payout.AmountCents;

            FinancialAccount forexSpillAccount =
                authData.CurrentOrganization.FinancialAccounts.IncomeCurrencyFluctuations;

            if (forexSpillAccount == null && payoutCents != -transactionCents)                           // the tx-negative is because it's a payout
            {
                throw new InvalidOperationException("Need forex gain/loss accounts for this operation"); // TODO: Autocreate?
            }

            if ((-transactionCents) < payoutCents)  // the tx-negative is because it's a payout
            {
                // This is a forex loss, not a gain which is the default
                forexSpillAccount = authData.CurrentOrganization.FinancialAccounts.CostsCurrencyFluctuations;
            }

            if (-transactionCents != payoutCents)
            {
                // Forex adjust
                transaction.AddRow(forexSpillAccount, -(payoutCents + transactionCents),
                                                          // plus because transactionCents is negative
                                   authData.CurrentUser); // Adds the forex adjustment so we can bind payout to tx and close
            }

            // The amounts should match now

            if (transaction.Rows.AmountCentsTotal != -payout.AmountCents)
            {
                throw new InvalidOperationException();
            }


            payout.BindToTransactionAndClose(transaction, authData.CurrentUser);
        }
Exemple #3
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge( PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;

            var transaction = new FinancialTransaction();
            transaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF");
            return transaction;
        }
Exemple #4
0
        public static string GetTransactionDisplayIdentity(int transactionId)
        {
            GetAuthenticationDataAndCulture(); // Sets culture

            FinancialTransaction tx = FinancialTransaction.FromIdentity(transactionId);

            return(tx.OrganizationSequenceId.ToString("N0"));
        }
 private static void SetDefaultTransaction(TransactionType transactionType)
 {
     SelectedTransaction = new FinancialTransaction {
         Type = (int)transactionType,
         IsExchangeModeActive = false,
         Currency             = ServiceLocator.Current.GetInstance <SettingDataAccess>().DefaultCurrency
     };
 }
 private static void CheckIfRecurringWasRemoved(FinancialTransaction transaction)
 {
     if (!transaction.IsRecurring && transaction.ReccuringTransactionId.HasValue)
     {
         RecurringTransactionRepository.Delete(transaction.RecurringTransaction);
         transaction.ReccuringTransactionId = null;
     }
 }
        public HttpResponseMessage PostScanned([FromBody] FinancialTransactionScannedCheck financialTransactionScannedCheck)
        {
            FinancialTransaction financialTransaction = financialTransactionScannedCheck.FinancialTransaction;

            financialTransaction.CheckMicrEncrypted = Encryption.EncryptString(financialTransactionScannedCheck.ScannedCheckMicr);
            financialTransaction.CheckMicrHash      = Encryption.GetSHA1Hash(financialTransactionScannedCheck.ScannedCheckMicr);
            return(this.Post(financialTransaction));
        }
Exemple #8
0
 private static async void PrehandleRemoveIfTransfer(FinancialTransaction transaction)
 {
     if (transaction.Type == (int)TransactionType.Transfer)
     {
         Func <double, double> amountFunc = x => - x;
         await HandleTransactionAmount(transaction, amountFunc, GetTargetAccountFunc());
     }
 }
Exemple #9
0
        public static FinancialTransaction Translate(PCODonation inputTransaction)
        {
            var transaction = new FinancialTransaction();

            transaction.Id = inputTransaction.id;

            if (inputTransaction.batchId.HasValue)
            {
                transaction.BatchId = inputTransaction.batchId.Value;
            }
            if (inputTransaction.payment_method == "check")
            {
                transaction.TransactionCode = inputTransaction.payment_check_number;
            }
            else if (inputTransaction.payment_method != "cash")
            {
                transaction.TransactionCode = inputTransaction.payment_last4;
            }

            transaction.TransactionDate = inputTransaction.received_at;

            transaction.AuthorizedPersonId = inputTransaction.personId;

            switch (inputTransaction.payment_method)
            {
            case "cash":
                transaction.CurrencyType = CurrencyType.Cash;
                break;

            case "check":
                transaction.CurrencyType = CurrencyType.Check;
                break;

            case "credit card":
            case "debit card":
            case "card":
                transaction.CurrencyType = CurrencyType.CreditCard;
                break;

            case "ach":
                transaction.CurrencyType = CurrencyType.ACH;
                break;

            case "non-cash":
                transaction.CurrencyType = CurrencyType.NonCash;
                break;

            default:
                transaction.CurrencyType = CurrencyType.Unknown;
                break;
            }

            transaction.CreatedDateTime = inputTransaction.created_at;

            transaction.ModifiedDateTime = inputTransaction.updated_at;

            return(transaction);
        }
Exemple #10
0
        public static FinancialTransaction Translate(DataRow row)
        {
            int?   ID;
            string field;
            FinancialTransaction transaction = new FinancialTransaction();

            // Identifiers
            transaction.Id      = row.Field <int>("CONTRIBUTION_ID");
            transaction.BatchId = row.Field <int>("BATCH_ID");
            ID = row.Field <int?>("PERSON_ID");
            if (ID != null)
            {
                transaction.AuthorizedPersonId = ID;              // May not be found in either the csIND or csINDBin tables
            }
            // Other fields
            transaction.TransactionCode  = row.Field <string>("CHECK_NO");
            transaction.TransactionDate  = row.Field <DateTime?>("BATCH_DT");
            transaction.CreatedDateTime  = row.Field <DateTime?>("CREATE_TS");
            transaction.ModifiedDateTime = row.Field <DateTime?>("UPDATE_TS");
            transaction.Summary          = row.Field <string>("NOTE");
            if (row.Field <string>("TAX_IND") == "1")
            {
                transaction.TransactionType = TransactionType.Contribution;
            }


            // Payment types can vary from Church to Church, so using the most popular ones here
            field = row.Field <string>("PAY_TYPE");
            switch (field)
            {
            case "L":      // Online
                transaction.TransactionSource = TransactionSource.Website;
                transaction.CurrencyType      = CurrencyType.CreditCard;
                break;

            case "C":      // Check
                transaction.TransactionSource = TransactionSource.OnsiteCollection;
                transaction.CurrencyType      = CurrencyType.Check;
                break;

            case "S":      // Cash
                transaction.TransactionSource = TransactionSource.OnsiteCollection;
                transaction.CurrencyType      = CurrencyType.Cash;
                break;

            case "O":                                                 // Other
                transaction.TransactionSource = TransactionSource.OnsiteCollection;
                transaction.CurrencyType      = CurrencyType.Unknown; // Slingshot won't import the Other value
                break;

            default:      // Unknown
                transaction.TransactionSource = TransactionSource.OnsiteCollection;
                transaction.CurrencyType      = CurrencyType.Unknown;
                break;
            }

            return(transaction);
        }
Exemple #11
0
        /// <summary>
        /// Credits the specified transaction.
        /// </summary>
        /// <param name="transaction">The transaction.</param>
        /// <param name="amount">The amount.</param>
        /// <param name="comment">The comment.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Credit(FinancialTransaction transaction, decimal amount, string comment, out string errorMessage)
        {
            errorMessage = string.Empty;

            var refundTransaction = new FinancialTransaction();

            refundTransaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF");
            return(refundTransaction);
        }
Exemple #12
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge(PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;

            var transaction = new FinancialTransaction();

            transaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF");
            return(transaction);
        }
Exemple #13
0
        public override void Run()
        {
            HotBitcoinAddressUnspent utxoToReturn = HotBitcoinAddressUnspent.FromIdentity(UtxoIdentity);
            HotBitcoinAddress        utxoAddress  = utxoToReturn.Address;
            BitcoinSecret            secretKey    = utxoAddress.PrivateKey;

            // TODO: Verify that the utxoAddress is an EchoTest address, i.e. has second path component == BitcoinUtility.BitcoinEchoTestIndex

            string returnAddress = BitcoinUtility.GetInputAddressesForTransaction(BitcoinChain.Cash, utxoToReturn.TransactionHash)[0]; // assumes at least one input address -- not coinbase

            // Return the money

            BitcoinTransactionInputs inputs = utxoToReturn.AsInputs;
            Int64 satoshisToReturn          = utxoToReturn.AmountSatoshis;

            Coin[]    coins       = inputs.Coins;
            ICoin[]   iCoins      = coins;
            ISecret[] privateKeys = utxoToReturn.AsInputs.PrivateKeys;

            TransactionBuilder txBuilder = new TransactionBuilder();

            txBuilder = txBuilder.SendFees(new Satoshis(BitcoinUtility.EchoFeeSatoshis));
            txBuilder = txBuilder.AddCoins(iCoins);
            txBuilder = txBuilder.AddKeys(privateKeys);

            if (returnAddress.StartsWith("1"))
            {
                txBuilder = txBuilder.Send(new BitcoinPubKeyAddress(returnAddress),
                                           new Satoshis(utxoToReturn.AmountSatoshis - BitcoinUtility.EchoFeeSatoshis));
            }
            else if (returnAddress.StartsWith("3"))
            {
                txBuilder = txBuilder.Send(new BitcoinScriptAddress(returnAddress, Network.Main),
                                           new Satoshis(utxoToReturn.AmountSatoshis - BitcoinUtility.EchoFeeSatoshis));
            }
            else
            {
                throw new ArgumentException("Unrecognized address format");
            }

            Transaction tx = txBuilder.BuildTransaction(true, SigHash.ForkId | SigHash.All);

            BitcoinUtility.BroadcastTransaction(tx, BitcoinChain.Cash);
            utxoToReturn.Delete();
            utxoAddress.UpdateTotal();

            // Update the ledger

            string tx2Description          = "Bitcoin echo test repayment";
            FinancialTransaction ledgerTx2 = FinancialTransaction.Create(this.Organization,
                                                                         DateTime.UtcNow, tx2Description);

            ledgerTx2.AddRow(this.Organization.FinancialAccounts.DebtsOther, satoshisToReturn, this.Person);
            ledgerTx2.AddRow(this.Organization.FinancialAccounts.AssetsBitcoinHot, -satoshisToReturn, this.Person);
            ledgerTx2.BlockchainHash = tx.GetHash().ToString();
        }
        private string FormatSummary(FinancialTransaction txn)
        {
            var sb = new StringBuilder();

            foreach (var transactionDetail in txn.TransactionDetails)
            {
                sb.AppendFormat("{0} (${1})<br>", transactionDetail.Account, transactionDetail.Amount);
            }
            return(sb.ToString());
        }
Exemple #15
0
        public AccountState Event(ObligationSettledConcept occurred)
        {
            var trans = new FinancialTransaction(occurred.FinancialConcept, occurred.Amount);

            this.Obligations[occurred.ObligationNumber]?.PostTransaction(trans);
            return(new AccountState(this.AccountNumber, this.CurrentBalance,
                                    this.AccountStatus, this.Obligations,
                                    SimulatedFields,
                                    AuditLog.Add(new StateLog("ObligationSettledConcept", occurred.UniqueGuid(), occurred.OccurredOn()))));
        }
Exemple #16
0
        private string FormatSummary(FinancialTransaction txn)
        {
            var sb = new StringBuilder();

            foreach (var transactionDetail in txn.TransactionDetails)
            {
                sb.AppendFormat("{0} ({2}{1})<br>", transactionDetail.Account, transactionDetail.Amount, GlobalAttributesCache.Value("CurrencySymbol"));
            }
            return(sb.ToString());
        }
Exemple #17
0
        public void Adding_Debit_Transaction_Updates_Account_Balance()
        {
            var initialBalance = acc.GetBalance();
            var trxToPost      = new FinancialTransaction(defaultDebitAmount, "Testing Debit Transaction", DateTime.UtcNow, FinancialTransactionType.DEBIT);

            acc.PostTransaction(trxToPost);
            var updatedBalance = acc.GetBalance();

            Assert.AreEqual(initialBalance - defaultDebitAmount, updatedBalance);
        }
Exemple #18
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;
            RequestMessage request = GetPaymentInfo(financialGateway, paymentInfo);

            if (request == null)
            {
                errorMessage = "Payment type not implemented";
                return(null);
            }

            request.purchaseTotals = GetTotals(paymentInfo);
            request.billTo         = GetBillTo(paymentInfo);
            request.item           = GetItems(paymentInfo);

            if (!paymentInfo.CurrencyTypeValue.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD)))
            {
                request.ecDebitService = new ECDebitService();
                request.ecDebitService.commerceIndicator = "internet";
                request.ecDebitService.run = "true";
            }
            else
            {
                request.ccAuthService = new CCAuthService();
                request.ccAuthService.commerceIndicator = "internet";
                request.ccAuthService.run    = "true";
                request.ccCaptureService     = new CCCaptureService();
                request.ccCaptureService.run = "true";
            }

            ReplyMessage reply = SubmitTransaction(financialGateway, request);

            if (reply != null)
            {
                if (reply.reasonCode.Equals("100"))      // SUCCESS
                {
                    var transactionGuid = new Guid(reply.merchantReferenceCode);
                    var transaction     = new FinancialTransaction {
                        Guid = transactionGuid
                    };
                    transaction.TransactionCode = reply.requestID;
                    return(transaction);
                }
                else
                {
                    errorMessage = string.Format("Your order was not approved.{0}", ProcessError(reply));
                }
            }
            else
            {
                errorMessage = "Invalid response from the financial gateway.";
            }

            return(null);
        }
Exemple #19
0
        /// <summary>
        /// Authorizes the specified payment info.
        /// </summary>
        /// <param name="financialGateway"></param>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Authorize(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage)
        {
            errorMessage = string.Empty;
            Response ppResponse = null;

            var invoice = GetInvoice(paymentInfo);
            var tender  = GetTender(paymentInfo);

            if (tender != null)
            {
                if (paymentInfo is ReferencePaymentInfo)
                {
                    var reference     = paymentInfo as ReferencePaymentInfo;
                    var ppTransaction = new ReferenceTransaction("Authorization", reference.TransactionCode, GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId);
                    ppResponse = ppTransaction.SubmitTransaction();
                }
                else
                {
                    var ppTransaction = new AuthorizationTransaction(GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId);
                    ppResponse = ppTransaction.SubmitTransaction();
                }
            }
            else
            {
                errorMessage = "Could not create tender from PaymentInfo";
            }

            if (ppResponse != null)
            {
                TransactionResponse txnResponse = ppResponse.TransactionResponse;
                if (txnResponse != null)
                {
                    if (txnResponse.Result == 0)   // Success
                    {
                        var transaction = new FinancialTransaction();
                        transaction.TransactionCode = txnResponse.Pnref;
                        return(transaction);
                    }
                    else
                    {
                        errorMessage = string.Format("[{0}] {1}", txnResponse.Result, txnResponse.RespMsg);
                    }
                }
                else
                {
                    errorMessage = "Invalid transaction response from the financial gateway";
                }
            }
            else
            {
                errorMessage = "Invalid response from the financial gateway.";
            }

            return(null);
        }
Exemple #20
0
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="itemKey">The item key.</param>
        /// <param name="itemKeyValue">The item key value.</param>
        public void ShowDetail(string itemKey, int itemKeyValue)
        {
            if (!itemKey.Equals("transactionId") && !!itemKey.Equals("batchfk"))
            {
                return;
            }

            FinancialTransaction transaction = null;

            if (!itemKeyValue.Equals(0))
            {
                transaction = new FinancialTransactionService(new RockContext()).Get(itemKeyValue);
            }
            else
            {
                transaction = new FinancialTransaction {
                    Id = 0
                };
            }

            hfIdTransValue.Value = transaction.Id.ToString();
            hfBatchId.Value      = PageParameter("financialBatchId");

            if (!readOnly)
            {
                lbEdit.Visible = true;
                if (transaction.Id > 0)
                {
                    ShowSummary(transaction);
                }
                else
                {
                    BindDropdowns();
                    ShowEdit(transaction);
                }

                gTransactionDetails.Actions.ShowAdd = true;
                gTransactionDetails.IsDeleteEnabled = true;
                pnlImageUpload.Visible = true;
            }
            else
            {
                lbEdit.Visible = false;
                ShowSummary(transaction);
                gTransactionDetails.Actions.ShowAdd = false;
                gTransactionDetails.IsDeleteEnabled = false;
                pnlImageUpload.Visible = false;
            }

            lbSave.Visible = !readOnly;
            LoadAccountDropDown();
            BindTransactionDetailGrid(transaction);
            BindDefinedTypeDropdown(ddlTransactionImageType, new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_IMAGE_TYPE), "Transaction Image Type");
            LoadRelatedImages(transaction.Id);
        }
Exemple #21
0
        /// <summary>
        /// Handles the RowDataBound event of the gContributions control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="GridViewRowEventArgs"/> instance containing the event data.</param>
        protected void gContributions_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            FinancialTransaction financialTransaction = e.Row.DataItem as FinancialTransaction;
            Literal lAddress = e.Row.FindControl("lAddress") as Literal;

            if (financialTransaction != null && lAddress != null && financialTransaction.AuthorizedPersonAliasId.HasValue)
            {
                var personAddress = financialTransaction.AuthorizedPersonAlias.Person.GetHomeLocation();
                lAddress.Text = personAddress.GetFullStreetAddress();
            }
        }
Exemple #22
0
        public void CloseBudget(Person closingPerson)
        {
            Int64 remainingFunds = -Budget.GetDeltaCents(CreatedDateTime, DateTime.Now);

            FinancialTransaction transaction = FinancialTransaction.Create(OrganizationId,
                                                                           DateTime.Now,
                                                                           "Closing conference #" + Identity);

            transaction.AddRow(Budget, remainingFunds, closingPerson);
            transaction.AddRow(Budget.Parent, -remainingFunds, closingPerson);
        }
Exemple #23
0
        public void FinancialTransactionShouldNotBeValid(string title, string description, double value)
        {
            var transactionDate = DateTime.Today;

            var financialTransaction = new FinancialTransaction(title, description, value, transactionDate);
            var financialValidator   = new FinancialTransactionValidator();
            var validationResult     = financialValidator.Validate(financialTransaction);

            Assert.False(validationResult.IsValid);
            Assert.NotEmpty(validationResult.Errors);
        }
Exemple #24
0
        public static async Task AddTransactionAmount(FinancialTransaction transaction)
        {
            PrehandleAddIfTransfer(transaction);

            Func <double, double> amountFunc = x =>
                                               transaction.Type == (int)TransactionType.Income
                    ? x
                    : -x;

            await HandleTransactionAmount(transaction, amountFunc, GetChargedAccountFunc());
        }
Exemple #25
0
    protected void Page_Load(object sender, EventArgs e)
    {
        _transaction = GetTransaction();

        if (!_authority.HasPermission(Permission.CanDoEconomyTransactions, _transaction.OrganizationId, -1, Authorization.Flag.ExactOrganization))
        {
            throw new UnauthorizedAccessException("Access Denied");
        }


        if (!Page.IsPostBack)
        {
            // Populate all data

            this.DatePicker.DateInput.Culture = new CultureInfo("sv-SE");
            this.DatePicker.SelectedDate      = _transaction.DateTime;
            this.TextDescription.Text         = _transaction.Description;
            this.TextDescription.Style.Add(HtmlTextWriterStyle.Width, "100%");
            this.TextAmount.Style.Add(HtmlTextWriterStyle.Width, "80px");
            this.DropAccounts.Style.Add(HtmlTextWriterStyle.Width, "200px");

            this.TextAmount.Text = (-_transaction.Rows.AmountTotal).ToString("N2", new CultureInfo("sv-SE"));

            PopulateAccounts(_transaction.OrganizationId);
            PopulateGrid();

            IHasIdentity dependency = _transaction.Dependency;

            if (dependency != null)
            {
                this.PanelModifiableTransaction.Visible   = false;
                this.PanelUnmodifiableTransaction.Visible = true;

                if (dependency is ExpenseClaim)
                {
                    this.LabelDependency.Text             = "Expense Claim #" + dependency.Identity.ToString();
                    this.PanelDependencyDocuments.Visible = true;
                    this.DocumentsDependency.Documents    = Documents.ForObject(dependency);
                }
                else if (dependency is Payout)
                {
                    this.PanelDependencyDocuments.Visible = false;
                    this.PanelPayoutDetails.Visible       = true;
                    this.LabelDependency.Text             = "Payout #" + dependency.Identity.ToString();
                    this.LabelPayoutIdentity.Text         = dependency.Identity.ToString();
                    this.LabelPayoutReference.Text        = ((Payout)dependency).Reference;
                }
            }
        }

        this.DocumentList.Documents = _transaction.Documents;

        Page.Title = "Editing Transaction #" + _transaction.Identity.ToString();
    }
Exemple #26
0
        public void SettledDateKeyGetsSetCorrectly()
        {
            var testList = TestDataHelper.GetAnalyticsSourceDateTestData();

            foreach (var keyValue in testList)
            {
                FinancialTransaction financialTransaction = new FinancialTransaction();
                financialTransaction.SettledDate = keyValue.Value;
                Assert.AreEqual(keyValue.Key, financialTransaction.SettledDateKey);
            }
        }
Exemple #27
0
 public IActionResult OnGet()
 {
     // Create a new instance of Financial transaction and set its FromUsername value from context.
     FinancialTransaction = new FinancialTransaction();
     FinancialTransaction.FromUsername = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.Name);
     if (FinancialTransaction.FromUsername == null)
     {
         return(Forbid());
     }
     return(Page());
 }
Exemple #28
0
        /// <summary>Deletes a transaction from the database.</summary>
        /// <param name="transaction">Transaction to be deleted</param>
        /// <param name="account">Account the transaction will be deleted from</param>
        /// <returns>Returns true if successful</returns>
        public static async Task <bool> DeleteFinancialTransaction(FinancialTransaction transaction, Account account)
        {
            bool success = false;

            if (await DatabaseInteraction.DeleteFinancialTransaction(transaction, account))
            {
                AllTransactions.Remove(transaction);
                success = true;
            }

            return(success);
        }
        /// <summary>Attempts to add a Transaction to the database.</summary>
        /// <returns>Returns true if successfully added</returns>
        private async Task <bool> AddTransaction()
        {
            FinancialTransaction newTransaction = new FinancialTransaction(await AppState.GetNextFinancialTransactionIndex(), DateTimeHelper.Parse(TransactionDate.SelectedDate),
                                                                           TxtPayee.Text, CmbMajorCategory.SelectedValue.ToString(), CmbMinorCategory.SelectedValue.ToString(),
                                                                           TxtMemo.Text, DecimalHelper.Parse(TxtOutflow.Text), DecimalHelper.Parse(TxtInflow.Text),
                                                                           _selectedAccount.Name);

            _selectedAccount.AddTransaction(newTransaction);
            AppState.AllTransactions.Add(newTransaction);

            return(await AppState.AddFinancialTransaction(newTransaction, _selectedAccount));
        }
Exemple #30
0
 private double HandleTransferAmount(FinancialTransaction transaction, double balance)
 {
     if (selectedAccount == transaction.ChargedAccount)
     {
         balance -= transaction.Amount;
     }
     else
     {
         balance += transaction.Amount;
     }
     return(balance);
 }
Exemple #31
0
 /// <summary>
 /// Sets the heading information.
 /// </summary>
 /// <param name="txn">The TXN.</param>
 private void SetHeadingInfo(FinancialTransaction txn)
 {
     if (txn.TransactionTypeValue != null)
     {
         hlType.Visible = true;
         hlType.Text    = txn.TransactionTypeValue.Value;
     }
     else
     {
         hlType.Visible = false;
     }
 }
        public static void PrepareEdit(FinancialTransaction transaction)
        {
            AddTransactionView.IsEdit     = true;
            AddTransactionView.IsTransfer = transaction.Type == (int)TransactionType.Transfer;
            if (transaction.ReccuringTransactionId.HasValue && transaction.RecurringTransaction != null)
            {
                AddTransactionView.IsEndless  = transaction.RecurringTransaction.IsEndless;
                AddTransactionView.Recurrence = transaction.RecurringTransaction.Recurrence;
            }

            TransactionRepository.Selected = transaction;
        }
    protected void Page_Load (object sender, EventArgs e)
    {
        _transaction = GetTransaction();

        if (!_authority.HasPermission(Permission.CanDoEconomyTransactions, _transaction.OrganizationId, -1, Authorization.Flag.ExactOrganization))
            throw new UnauthorizedAccessException("Access Denied");


        if (!Page.IsPostBack)
        {
            // Populate all data

            this.DatePicker.DateInput.Culture = new CultureInfo("sv-SE");
            this.DatePicker.SelectedDate = _transaction.DateTime;
            this.TextDescription.Text = _transaction.Description;
            this.TextDescription.Style.Add(HtmlTextWriterStyle.Width, "100%");
            this.TextAmount.Style.Add(HtmlTextWriterStyle.Width, "80px");
            this.DropAccounts.Style.Add(HtmlTextWriterStyle.Width, "200px");

            this.TextAmount.Text = (-_transaction.Rows.AmountTotal).ToString("N2", new CultureInfo("sv-SE"));

            PopulateAccounts(_transaction.OrganizationId);
            PopulateGrid();

            IHasIdentity dependency = _transaction.Dependency;

            if (dependency != null)
            {
                this.PanelModifiableTransaction.Visible = false;
                this.PanelUnmodifiableTransaction.Visible = true;

                if (dependency is ExpenseClaim)
                {
                    this.LabelDependency.Text = "Expense Claim #" + dependency.Identity.ToString();
                    this.PanelDependencyDocuments.Visible = true;
                    this.DocumentsDependency.Documents = Documents.ForObject(dependency);
                }
                else if (dependency is Payout)
                {
                    this.PanelDependencyDocuments.Visible = false;
                    this.PanelPayoutDetails.Visible = true;
                    this.LabelDependency.Text = "Payout #" + dependency.Identity.ToString();
                    this.LabelPayoutIdentity.Text = dependency.Identity.ToString();
                    this.LabelPayoutReference.Text = ((Payout) dependency).Reference;
                }
            }
        }

        this.DocumentList.Documents = _transaction.Documents;

        Page.Title = "Editing Transaction #" + _transaction.Identity.ToString();
    }
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="itemKey">The item key.</param>
        /// <param name="itemKeyValue">The item key value.</param>
        public void ShowDetail( string itemKey, int itemKeyValue )
        {
            if ( !itemKey.Equals( "transactionId" ) && !!itemKey.Equals( "batchfk" ) )
            {
                return;
            }

            FinancialTransaction transaction = null;
            if ( !itemKeyValue.Equals( 0 ) )
            {
                transaction = new FinancialTransactionService( new RockContext() ).Get( itemKeyValue );
            }
            else
            {
                transaction = new FinancialTransaction { Id = 0 };
            }

            hfIdTransValue.Value = transaction.Id.ToString();
            hfBatchId.Value = PageParameter( "financialBatchId" );

            if ( !readOnly )
            {
                lbEdit.Visible = true;
                if ( transaction.Id > 0 )
                {
                    ShowSummary( transaction );
                }
                else
                {
                    BindDropdowns();
                    ShowEdit( transaction );
                }

                gTransactionDetails.Actions.ShowAdd = true;
                gTransactionDetails.IsDeleteEnabled = true;
                pnlImageUpload.Visible = true;
            }
            else
            {
                lbEdit.Visible = false;
                ShowSummary( transaction );
                gTransactionDetails.Actions.ShowAdd = false;
                gTransactionDetails.IsDeleteEnabled = false;
                pnlImageUpload.Visible = false;
            }

            lbSave.Visible = !readOnly;
            LoadAccountDropDown();
            BindTransactionDetailGrid( transaction );
            BindDefinedTypeDropdown( ddlTransactionImageType, new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_IMAGE_TYPE ), "Transaction Image Type" );
            LoadRelatedImages( transaction.Id );
        }
        /// <summary>
        /// Deletes the specified item.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <returns></returns>
        public override bool Delete( FinancialTransaction item )
        {
            if ( item.FinancialPaymentDetailId.HasValue )
            {
                var paymentDetailsService = new FinancialPaymentDetailService( (Rock.Data.RockContext)this.Context );
                var paymentDetail = paymentDetailsService.Get( item.FinancialPaymentDetailId.Value );
                if ( paymentDetail != null )
                {
                    paymentDetailsService.Delete( paymentDetail );
                }
            }

            return base.Delete( item );
        }
        /// <summary>
        /// Formats the type of the currency.
        /// </summary>
        /// <param name="txn">The TXN.</param>
        /// <returns></returns>
        protected string FormatCurrencyType( FinancialTransaction txn )
        {
            string currencyType = string.Empty;
            string creditCardType = string.Empty;

            if ( txn.FinancialPaymentDetail != null && txn.FinancialPaymentDetail.CurrencyTypeValueId.HasValue )
            {
                int currencyTypeId = txn.FinancialPaymentDetail.CurrencyTypeValueId.Value;

                var currencyTypeValue = DefinedValueCache.Read( currencyTypeId );
                currencyType = currencyTypeValue != null ? currencyTypeValue.Value : string.Empty;

                if ( txn.FinancialPaymentDetail.CreditCardTypeValueId.HasValue )
                {
                    int creditCardTypeId = txn.FinancialPaymentDetail.CreditCardTypeValueId.Value;
                    var creditCardTypeValue = DefinedValueCache.Read( creditCardTypeId );
                    creditCardType = creditCardTypeValue != null ? creditCardTypeValue.Value : string.Empty;

                    return string.Format( "{0} - {1}", currencyType, creditCardType );
                }
            }

            return currencyType;
        }
Exemple #37
0
        /// <summary>
        /// Creates the giving records for the given parameters.
        /// </summary>
        /// <param name="personGuid">The person unique identifier.</param>
        /// <param name="startingDate">The starting date.</param>
        /// <param name="endDate">The end date.</param>
        /// <param name="frequency">The frequency (onetime, weekly, monthly).</param>
        /// <param name="percentGive">The percent give.</param>
        /// <param name="growRatePercent">The grow rate percent.</param>
        /// <param name="growFrequencyWeeks">The grow frequency weeks.</param>
        /// <param name="specialGiftPercent">The special gift percent.</param>
        /// <param name="accountAmountDict">The account amount dictionary.</param>
        /// <param name="circularImageList">A circular linked list of imageUrls to use for the fake contribution checks.</param>
        /// <param name="rockContexe">A rock context.</param>
        private void CreateGiving( Guid personGuid, DateTime startingDate, DateTime endDate, Frequency frequency, int percentGive, int growRatePercent, int growFrequencyWeeks, int specialGiftPercent, Dictionary<int, decimal> accountAmountDict, LinkedList<string> circularImageList, RockContext rockContext )
        {
            int weekNumber = 0;
            DateTime monthly = startingDate;

            var currencyTypeCheck = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK.AsGuid() );

            var imageUrlNode = circularImageList.First ?? null;
            // foreach weekend or monthly between the starting and ending date...
            for ( DateTime date = startingDate; date <= endDate; date = frequency == Frequency.weekly ? date.AddDays( 7 ) : frequency == Frequency.monthly ? date.AddMonths( 1 ) : endDate.AddDays(1) )
            {
                weekNumber = (int)(date - startingDate).TotalDays / 7;

                // increase by growRatePercent every growFrequencyWeeks
                if ( growFrequencyWeeks != 0 && growRatePercent != 0 && weekNumber !=0 && weekNumber % growFrequencyWeeks == 0 )
                {
                    var copy = accountAmountDict.ToDictionary( entry => entry.Key, entry => entry.Value );
                    foreach ( var item in accountAmountDict )
                    {
                        decimal amount = Math.Round( ( item.Value * 0.01M ) + item.Value, 0 );
                        copy[item.Key] = amount;
                    }
                    accountAmountDict = copy;
                }

                // randomized skip/missed weeks
                int summerFactor = ( 7 <= date.Month && date.Month <= 9 ) ? summerPercentFactor : 0;
                if ( _random.Next( 0, 100 ) > percentGive - summerFactor )
                {
                    continue; // skip this week
                }

                FinancialBatch batch;
                if ( _contributionBatches.ContainsKey( date ) )
                {
                    batch = _contributionBatches[date];
                }
                else
                {
                    batch = new FinancialBatch {
                        Id = 0,
                        Guid = Guid.NewGuid(),
                        BatchStartDateTime = date,
                        BatchEndDateTime = date,
                        Status = BatchStatus.Closed,
                        ControlAmount = 0,
                        Name = string.Format( "SampleData{0}", date.ToJavascriptMilliseconds() ),
                        CreatedByPersonAliasId = CurrentPerson.PrimaryAliasId };
                    _contributionBatches.Add( date, batch );
                }

                // Set up the new transaction
                FinancialTransaction financialTransaction = new FinancialTransaction
                {
                    TransactionTypeValueId = _transactionTypeContributionId,
                    Guid = Guid.NewGuid(),
                    TransactionDateTime = date,
                    AuthorizedPersonAliasId = _peopleAliasDictionary[personGuid]
                };

                financialTransaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                financialTransaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeCheck.Id;
                financialTransaction.FinancialPaymentDetail.Guid = Guid.NewGuid();

                // Add a transaction detail record for each account they're donating to
                foreach ( var item in accountAmountDict )
                {
                    FinancialTransactionDetail transactionDetail = new FinancialTransactionDetail {
                        AccountId = item.Key,
                        Amount = item.Value,
                        Guid = Guid.NewGuid()
                    };

                    financialTransaction.TransactionDetails.Add( transactionDetail );
                }

                // Add the image to the transaction (if any)
                if ( imageUrlNode != null )
                {
                    FinancialTransactionImage transactionImage = new FinancialTransactionImage
                    {
                        BinaryFile = SaveImage( imageUrlNode.Value, _checkImageBinaryFileType, _checkImageBinaryFileTypeSettings, rockContext ),
                        Guid = Guid.NewGuid(),
                    };
                    financialTransaction.Images.Add( transactionImage );
                    imageUrlNode = imageUrlNode.Next ?? imageUrlNode.List.First;
                }

                // Update the batch with the new control amount
                batch.ControlAmount += financialTransaction.TotalAmount;
                batch.Transactions.Add( financialTransaction );
            }
        }
Exemple #38
0
        /// <summary>
        /// Gets the bill to from a transaction.
        /// </summary>
        /// <param name="transaction">The transaction.</param>
        /// <returns></returns>
        private BillTo GetBillTo( FinancialTransaction transaction )
        {
            BillTo billingInfo = new BillTo();
            billingInfo.customerID = transaction.AuthorizedPersonAlias.Id.ToString();
            billingInfo.firstName = transaction.AuthorizedPersonAlias.Person.FirstName.Left( 50 );       // up to 50 chars
            billingInfo.lastName = transaction.AuthorizedPersonAlias.Person.LastName.Left( 50 );         // up to 60 chars
            billingInfo.email = transaction.AuthorizedPersonAlias.Person.Email.Left( 255 );              // up to 255 chars
            billingInfo.ipAddress = Dns.GetHostEntry( Dns.GetHostName() )
                .AddressList.FirstOrDefault( ip => ip.AddressFamily == AddressFamily.InterNetwork ).ToString();

            return billingInfo;
        }
 private string FormatSummary( FinancialTransaction txn )
 {
     var sb = new StringBuilder();
     foreach ( var transactionDetail in txn.TransactionDetails )
     {
         sb.AppendFormat( "{0} (${1})<br>", transactionDetail.Account, transactionDetail.Amount );
     }
     return sb.ToString();
 }
Exemple #40
0
        /// <summary>
        /// Gets the reference number from the gateway for converting a transaction to a billing profile.
        /// </summary>
        /// <param name="transaction">The transaction.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override string GetReferenceNumber( FinancialTransaction transaction, out string errorMessage )
        {
            errorMessage = string.Empty;
            var financialGateway = transaction.FinancialGateway;
            RequestMessage request = GetMerchantInfo( financialGateway );
            request.billTo = GetBillTo( transaction );
            request.recurringSubscriptionInfo = new RecurringSubscriptionInfo();
            request.recurringSubscriptionInfo.frequency = "ON-DEMAND";
            request.recurringSubscriptionInfo.amount = "0";
            request.paySubscriptionCreateService = new PaySubscriptionCreateService();
            request.paySubscriptionCreateService.run = "true";
            request.paySubscriptionCreateService.paymentRequestID = transaction.TransactionCode;

            // Get the reference code
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode == GATEWAY_RESPONSE_SUCCESS )
            {
                return reply.paySubscriptionCreateReply.subscriptionID;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = ProcessError( reply );
            }

            return string.Empty;
        }
        /// <summary>
        /// Processes the payments.
        /// </summary>
        /// <param name="gateway">The gateway.</param>
        /// <param name="batchNamePrefix">The batch name prefix.</param>
        /// <param name="payments">The payments.</param>
        /// <param name="batchUrlFormat">The batch URL format.</param>
        /// <returns></returns>
        public static string ProcessPayments( FinancialGateway gateway, string batchNamePrefix, List<Payment> payments, string batchUrlFormat = "" )
        {
            int totalPayments = 0;
            int totalAlreadyDownloaded = 0;
            int totalNoScheduledTransaction = 0;
            int totalAdded = 0;

            var batches = new List<FinancialBatch>();
            var batchSummary = new Dictionary<Guid, List<Payment>>();
            var initialControlAmounts = new Dictionary<Guid, decimal>();

            var allBatchChanges = new Dictionary<Guid, List<string>>();
            var allTxnChanges = new Dictionary<Guid, List<string>>();
            var txnPersonNames = new Dictionary<Guid, string>();

            using ( var rockContext = new RockContext() )
            {
                var accountService = new FinancialAccountService( rockContext );
                var txnService = new FinancialTransactionService( rockContext );
                var batchService = new FinancialBatchService( rockContext );
                var scheduledTxnService = new FinancialScheduledTransactionService( rockContext );

                var contributionTxnType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() );

                var defaultAccount = accountService.Queryable()
                    .Where( a =>
                        a.IsActive &&
                        !a.ParentAccountId.HasValue &&
                        ( !a.StartDate.HasValue || a.StartDate.Value <= RockDateTime.Now ) &&
                        ( !a.EndDate.HasValue || a.EndDate.Value >= RockDateTime.Now )
                        )
                    .OrderBy( a => a.Order )
                    .FirstOrDefault();

                var batchTxnChanges = new Dictionary<Guid, List<string>>();
                var batchBatchChanges = new Dictionary<Guid, List<string>>();

                foreach ( var payment in payments.Where( p => p.Amount > 0.0M ) )
                {
                    totalPayments++;

                    // Only consider transactions that have not already been added
                    if ( txnService.GetByTransactionCode( payment.TransactionCode ) == null )
                    {
                        var scheduledTransaction = scheduledTxnService.GetByScheduleId( payment.GatewayScheduleId );
                        if ( scheduledTransaction != null )
                        {
                            scheduledTransaction.IsActive = payment.ScheduleActive;

                            var txnChanges = new List<string>();

                            var transaction = new FinancialTransaction();
                            transaction.FinancialPaymentDetail = new FinancialPaymentDetail();

                            transaction.Guid = Guid.NewGuid();
                            allTxnChanges.Add( transaction.Guid, txnChanges );
                            txnChanges.Add( "Created Transaction (Downloaded from Gateway)" );

                            transaction.TransactionCode = payment.TransactionCode;
                            History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode );

                            transaction.TransactionDateTime = payment.TransactionDateTime;
                            History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime );

                            transaction.ScheduledTransactionId = scheduledTransaction.Id;

                            transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId;
                            History.EvaluateChange( txnChanges, "Person", string.Empty, scheduledTransaction.AuthorizedPersonAlias.Person.FullName );
                            txnPersonNames.Add( transaction.Guid, scheduledTransaction.AuthorizedPersonAlias.Person.FullName );

                            transaction.FinancialGatewayId = gateway.Id;
                            History.EvaluateChange( txnChanges, "Gateway", string.Empty, gateway.Name );

                            transaction.TransactionTypeValueId = contributionTxnType.Id;
                            History.EvaluateChange( txnChanges, "Type", string.Empty, contributionTxnType.Value );

                            var currencyTypeValue = payment.CurrencyTypeValue;
                            var creditCardTypevalue = payment.CreditCardTypeValue;

                            if ( scheduledTransaction.FinancialPaymentDetail != null )
                            {
                                if ( currencyTypeValue == null && scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.HasValue )
                                {
                                    currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.Value );
                                }

                                if ( creditCardTypevalue == null && scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.HasValue )
                                {
                                    creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.Value );
                                }

                                transaction.FinancialPaymentDetail.AccountNumberMasked = scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked;
                                transaction.FinancialPaymentDetail.NameOnCardEncrypted = scheduledTransaction.FinancialPaymentDetail.NameOnCardEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationYearEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted;
                            }

                            if ( currencyTypeValue != null )
                            {
                                transaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeValue.Id;
                                History.EvaluateChange( txnChanges, "Currency Type", string.Empty, currencyTypeValue.Value );
                            }
                            if ( creditCardTypevalue != null )
                            {
                                transaction.FinancialPaymentDetail.CreditCardTypeValueId = creditCardTypevalue.Id;
                                History.EvaluateChange( txnChanges, "Credit Card Type", string.Empty, creditCardTypevalue.Value );
                            }

                            //transaction.SourceTypeValueId = DefinedValueCache.Read( sourceGuid ).Id;

                            // Try to allocate the amount of the transaction based on the current scheduled transaction accounts
                            decimal remainingAmount = payment.Amount;
                            foreach ( var detail in scheduledTransaction.ScheduledTransactionDetails.Where( d => d.Amount != 0.0M ) )
                            {
                                var transactionDetail = new FinancialTransactionDetail();
                                transactionDetail.AccountId = detail.AccountId;

                                if ( detail.Amount <= remainingAmount )
                                {
                                    // If the configured amount for this account is less than or equal to the remaining
                                    // amount, allocate the configured amount
                                    transactionDetail.Amount = detail.Amount;
                                    remainingAmount -= detail.Amount;
                                }
                                else
                                {
                                    // If the configured amount is greater than the remaining amount, only allocate
                                    // the remaining amount
                                    transaction.Summary = "Note: Downloaded transaction amount was less than the configured allocation amounts for the Scheduled Transaction.";
                                    detail.Amount = remainingAmount;
                                    detail.Summary = "Note: The downloaded amount was not enough to apply the configured amount to this account.";
                                    remainingAmount = 0.0M;
                                }

                                transaction.TransactionDetails.Add( transactionDetail );

                                History.EvaluateChange( txnChanges, detail.Account.Name, 0.0M.ToString( "C2" ), transactionDetail.Amount.ToString( "C2" ) );
                                History.EvaluateChange( txnChanges, "Summary", string.Empty, transactionDetail.Summary );

                                if ( remainingAmount <= 0.0M )
                                {
                                    // If there's no amount left, break out of details
                                    break;
                                }
                            }

                            // If there's still amount left after allocating based on current config, add the remainder
                            // to the account that was configured for the most amount
                            if ( remainingAmount > 0.0M )
                            {
                                transaction.Summary = "Note: Downloaded transaction amount was greater than the configured allocation amounts for the Scheduled Transaction.";
                                var transactionDetail = transaction.TransactionDetails
                                    .OrderByDescending( d => d.Amount )
                                    .First();
                                if ( transactionDetail == null && defaultAccount != null )
                                {
                                    transactionDetail = new FinancialTransactionDetail();
                                    transactionDetail.AccountId = defaultAccount.Id;
                                }
                                if ( transactionDetail != null )
                                {
                                    transactionDetail.Amount += remainingAmount;
                                    transactionDetail.Summary = "Note: Extra amount was applied to this account.";
                                }

                                History.EvaluateChange( txnChanges, defaultAccount.Name, 0.0M.ToString( "C2" ), transactionDetail.Amount.ToString( "C2" ) );
                                History.EvaluateChange( txnChanges, "Summary", string.Empty, transactionDetail.Summary );
                            }

                            // Get the batch
                            var batch = batchService.Get(
                                batchNamePrefix,
                                currencyTypeValue,
                                creditCardTypevalue,
                                transaction.TransactionDateTime.Value,
                                gateway.GetBatchTimeOffset(),
                                batches );

                            var batchChanges = new List<string>();
                            if ( batch.Id != 0 )
                            {
                                initialControlAmounts.AddOrIgnore( batch.Guid, batch.ControlAmount );
                            }
                            batch.ControlAmount += transaction.TotalAmount;

                            batch.Transactions.Add( transaction );

                            // Add summary
                            if ( !batchSummary.ContainsKey( batch.Guid ) )
                            {
                                batchSummary.Add( batch.Guid, new List<Payment>() );
                            }
                            batchSummary[batch.Guid].Add( payment );

                            totalAdded++;
                        }
                        else
                        {
                            totalNoScheduledTransaction++;
                        }
                    }
                    else
                    {
                        totalAlreadyDownloaded++;
                    }
                }

                foreach ( var batch in batches )
                {
                    var batchChanges = new List<string>();
                    allBatchChanges.Add( batch.Guid, batchChanges );

                    if ( batch.Id == 0 )
                    {
                        batchChanges.Add( "Generated the batch" );
                        History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name );
                        History.EvaluateChange( batchChanges, "Status", null, batch.Status );
                        History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime );
                        History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime );
                    }

                    if ( initialControlAmounts.ContainsKey( batch.Guid ) )
                    {
                        History.EvaluateChange( batchChanges, "Control Amount", initialControlAmounts[batch.Guid].ToString( "C2" ), batch.ControlAmount.ToString( "C2" ) );
                    }
                }

                rockContext.WrapTransaction( () =>
                {
                    rockContext.SaveChanges();

                    foreach ( var batch in batches )
                    {
                        HistoryService.SaveChanges(
                            rockContext,
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            batch.Id,
                            allBatchChanges[batch.Guid]
                        );

                        foreach ( var transaction in batch.Transactions )
                        {
                            if ( allTxnChanges.ContainsKey( transaction.Guid ) )
                            {
                                HistoryService.SaveChanges(
                                    rockContext,
                                    typeof( FinancialBatch ),
                                    Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                                    batch.Id,
                                    allTxnChanges[transaction.Guid],
                                    txnPersonNames[transaction.Guid],
                                    typeof( FinancialTransaction ),
                                    transaction.Id
                                );
                            }
                        }
                    }

                    rockContext.SaveChanges();
                } );
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendFormat( "<li>{0} {1} downloaded.</li>", totalPayments.ToString( "N0" ),
                ( totalPayments == 1 ? "payment" : "payments" ) );

            if ( totalAlreadyDownloaded > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} previously downloaded and {2} already been added.</li>", totalAlreadyDownloaded.ToString( "N0" ),
                    ( totalAlreadyDownloaded == 1 ? "payment was" : "payments were" ),
                    ( totalAlreadyDownloaded == 1 ? "has" : "have" ) );
            }

            if ( totalNoScheduledTransaction > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} could not be matched to an existing scheduled payment profile.</li>", totalNoScheduledTransaction.ToString( "N0" ),
                    ( totalNoScheduledTransaction == 1 ? "payment" : "payments" ) );
            }

            sb.AppendFormat( "<li>{0} {1} successfully added.</li>", totalAdded.ToString( "N0" ),
                ( totalAdded == 1 ? "payment was" : "payments were" ) );

            foreach ( var batchItem in batchSummary )
            {
                int items = batchItem.Value.Count;
                if (items > 0)
                {
                    var batch = batches
                        .Where( b => b.Guid.Equals( batchItem.Key ) )
                        .FirstOrDefault();

                    string batchName = string.Format("'{0} ({1})'", batch.Name, batch.BatchStartDateTime.Value.ToString("d"));
                    if ( !string.IsNullOrWhiteSpace( batchUrlFormat ) )
                    {
                        batchName = string.Format( "<a href='{0}'>{1}</a>", string.Format( batchUrlFormat, batch.Id ), batchName );
                    }

                    decimal sum = batchItem.Value.Select( p => p.Amount ).Sum();

                    string summaryformat = items == 1 ?
                        "<li>{0} transaction of {1} was added to the {2} batch.</li>" :
                        "<li>{0} transactions totaling {1} were added to the {2} batch</li>";

                    sb.AppendFormat( summaryformat, items.ToString( "N0" ), sum.ToString( "C2" ), batchName );
                }
            }

            return sb.ToString();
        }
Exemple #42
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge( PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;
            Response ppResponse = null;

            var invoice = GetInvoice( paymentInfo );
            var tender = GetTender( paymentInfo );

            if ( tender != null )
            {
                if ( paymentInfo is ReferencePaymentInfo )
                {
                    var reference = paymentInfo as ReferencePaymentInfo;
                    var ppTransaction = new ReferenceTransaction( "Sale", reference.TransactionCode, GetUserInfo(), GetConnection(), invoice, tender, PayflowUtility.RequestId );
                    ppResponse = ppTransaction.SubmitTransaction();
                }
                else
                {
                    var ppTransaction = new SaleTransaction( GetUserInfo(), GetConnection(), invoice, tender, PayflowUtility.RequestId );
                    ppResponse = ppTransaction.SubmitTransaction();
                }
            }
            else
            {
                errorMessage = "Could not create tender from PaymentInfo";
            }

            if ( ppResponse != null )
            {
                TransactionResponse txnResponse = ppResponse.TransactionResponse;
                if ( txnResponse != null )
                {
                    if ( txnResponse.Result == 0 ) // Success
                    {
                        var transaction = new FinancialTransaction();
                        transaction.TransactionCode = txnResponse.Pnref;
                        return transaction;
                    }
                    else
                    {
                        errorMessage = string.Format( "[{0}] {1}", txnResponse.Result, txnResponse.RespMsg );
                    }
                }
                else
                {
                    errorMessage = "Invalid transaction response from the financial gateway";
                }
            }
            else
            {
                errorMessage = "Invalid response from the financial gateway.";
            }

            return null;
        }
Exemple #43
0
 /// <summary>
 /// Gets an optional reference identifier needed to process future transaction from saved account.
 /// </summary>
 /// <param name="transaction">The transaction.</param>
 /// <param name="errorMessage">The error message.</param>
 /// <returns></returns>
 public override string GetReferenceNumber( FinancialTransaction transaction, out string errorMessage )
 {
     errorMessage = string.Empty;
     return string.Empty;
 }
Exemple #44
0
        /// <summary>
        /// Authorizes/tokenizes the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Authorize( FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;
            RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo );

            if ( request == null )
            {
                errorMessage = "Payment type not implemented";
                return null;
            }

            if ( request.recurringSubscriptionInfo == null )
            {
                request.recurringSubscriptionInfo = new RecurringSubscriptionInfo();
            }

            request.recurringSubscriptionInfo.frequency = "ON-DEMAND";
            request.recurringSubscriptionInfo.amount = paymentInfo.Amount.ToString();
            request.paySubscriptionCreateService = new PaySubscriptionCreateService();
            request.paySubscriptionCreateService.run = "true";
            request.purchaseTotals = GetTotals();
            request.billTo = GetBillTo( paymentInfo );
            request.item = GetItems( paymentInfo );

            request.subscription = new Subscription();
            if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) )
            {
                request.subscription.paymentMethod = "check";
            }

            if ( paymentInfo is ReferencePaymentInfo )
            {
                request.paySubscriptionCreateService.paymentRequestID = ( (ReferencePaymentInfo)paymentInfo ).TransactionCode;
            }

            // Authorize the transaction
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) )
            {
                var transactionGuid = new Guid( reply.merchantReferenceCode );
                var transaction = new FinancialTransaction { Guid = transactionGuid };
                transaction.TransactionCode = reply.requestID;
                return transaction;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = string.Format( "Unable to authorize this transaction.{0}", ProcessError( reply ) );
            }

            return null;
        }
Exemple #45
0
        /// <summary>
        /// Credits (Refunds) the specified transaction.
        /// </summary>
        /// <param name="origTransaction">The original transaction.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Credit( FinancialTransaction origTransaction, decimal amount, string comment, out string errorMessage )
        {
            errorMessage = string.Empty;

            if ( origTransaction == null )
            {
                errorMessage = "Original transaction cannot be null";
                return null;
            }

            if ( string.IsNullOrWhiteSpace( origTransaction.TransactionCode ) )
            {
                errorMessage = "The transaction must have a TransactionCode to process a refund/credit";
                return null;
            }

            if ( origTransaction.FinancialGateway == null )
            {
                errorMessage = "The transaction must have a FinancialGateway to process a refund/credit";
                return null;
            }

            var financialGateway = origTransaction.FinancialGateway;
            var request = GetMerchantInfo( financialGateway );

            request.ccCreditService = new CCCreditService
            {
                run = "true",
                captureRequestID = origTransaction.TransactionCode
            };

            request.comments = comment;
            request.purchaseTotals = GetTotals();
            request.purchaseTotals.grandTotalAmount = amount.ToString();

            // Credit the transaction
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) )
            {
                var transactionGuid = new Guid( reply.merchantReferenceCode );
                var transaction = new FinancialTransaction
                {
                    Guid = transactionGuid,
                    TransactionCode = reply.requestID,
                    Summary = comment
                };
                return transaction;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = string.Format( "Unable to credit this transaction.{0}", ProcessError( reply ) );
            }

            return null;
        }
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="transactionId">The transaction identifier.</param>
        public void ShowDetail( int transactionId, int? batchId )
        {
            FinancialTransaction txn = null;

            bool editAllowed = true;

            var rockContext = new RockContext();

            if ( !transactionId.Equals( 0 ) )
            {
                txn = GetTransaction( transactionId, rockContext );
                if ( txn != null )
                {
                    editAllowed = txn.IsAuthorized( Authorization.EDIT, CurrentPerson );
                }
            }

            if ( txn == null )
            {
                txn = new FinancialTransaction { Id = 0 };
                txn.BatchId = batchId;
            }

            hfTransactionId.Value = txn.Id.ToString();
            hfBatchId.Value = batchId.HasValue ? batchId.Value.ToString() : string.Empty;

            bool readOnly = false;

            nbEditModeMessage.Text = string.Empty;
            if ( !editAllowed || !IsUserAuthorized( Authorization.EDIT ) )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( FinancialTransaction.FriendlyTypeName );
            }

            if ( readOnly )
            {
                lbEdit.Visible = false;
                ShowReadOnlyDetails( txn );
            }
            else
            {
                lbEdit.Visible = true;
                if ( txn.Id > 0 )
                {
                    ShowReadOnlyDetails( txn );
                }
                else
                {
                    ShowEditDetails( txn, rockContext );
                }
            }

            lbSave.Visible = !readOnly;
        }
        /// <summary>
        /// Processes the payments.
        /// </summary>
        /// <param name="gateway">The gateway.</param>
        /// <param name="batchNamePrefix">The batch name prefix.</param>
        /// <param name="payments">The payments.</param>
        /// <param name="batchUrlFormat">The batch URL format.</param>
        /// <param name="receiptEmail">The receipt email.</param>
        /// <returns></returns>
        public static string ProcessPayments( FinancialGateway gateway, string batchNamePrefix, List<Payment> payments, string batchUrlFormat = "", Guid? receiptEmail = null )
        {
            int totalPayments = 0;
            int totalAlreadyDownloaded = 0;
            int totalNoScheduledTransaction = 0;
            int totalAdded = 0;
            int totalReversals = 0;
            int totalStatusChanges = 0;

            var batches = new List<FinancialBatch>();
            var batchSummary = new Dictionary<Guid, List<Decimal>>();
            var initialControlAmounts = new Dictionary<Guid, decimal>();

            var txnPersonNames = new Dictionary<Guid, string>();

            var gatewayComponent = gateway.GetGatewayComponent();

            var newTransactions = new List<FinancialTransaction>();

            using ( var rockContext = new RockContext() )
            {
                var accountService = new FinancialAccountService( rockContext );
                var txnService = new FinancialTransactionService( rockContext );
                var batchService = new FinancialBatchService( rockContext );
                var scheduledTxnService = new FinancialScheduledTransactionService( rockContext );

                var contributionTxnType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() );

                var defaultAccount = accountService.Queryable()
                    .Where( a =>
                        a.IsActive &&
                        !a.ParentAccountId.HasValue &&
                        ( !a.StartDate.HasValue || a.StartDate.Value <= RockDateTime.Now ) &&
                        ( !a.EndDate.HasValue || a.EndDate.Value >= RockDateTime.Now )
                        )
                    .OrderBy( a => a.Order )
                    .FirstOrDefault();

                var batchTxnChanges = new Dictionary<Guid, List<string>>();
                var batchBatchChanges = new Dictionary<Guid, List<string>>();
                var scheduledTransactionIds = new List<int>();

                foreach ( var payment in payments.Where( p => p.Amount > 0.0M ) )
                {
                    totalPayments++;

                    var scheduledTransaction = scheduledTxnService.GetByScheduleId( payment.GatewayScheduleId );
                    if ( scheduledTransaction != null )
                    {
                        // Find existing payments with same transaction code
                        var txns = txnService
                            .Queryable( "TransactionDetails" )
                            .Where( t => t.TransactionCode == payment.TransactionCode )
                            .ToList();

                        // Calculate whether a transaction needs to be added
                        var txnAmount = CalculateTransactionAmount( payment, txns );
                        if ( txnAmount != 0.0M )
                        {
                            scheduledTransactionIds.Add( scheduledTransaction.Id );
                            if ( payment.ScheduleActive.HasValue )
                            {
                                scheduledTransaction.IsActive = payment.ScheduleActive.Value;
                            }

                            var transaction = new FinancialTransaction();
                            transaction.FinancialPaymentDetail = new FinancialPaymentDetail();

                            transaction.Guid = Guid.NewGuid();
                            transaction.TransactionCode = payment.TransactionCode;
                            transaction.TransactionDateTime = payment.TransactionDateTime;
                            transaction.Status = payment.Status;
                            transaction.StatusMessage = payment.StatusMessage;
                            transaction.ScheduledTransactionId = scheduledTransaction.Id;
                            transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId;
                            transaction.SourceTypeValueId = scheduledTransaction.SourceTypeValueId;
                            txnPersonNames.Add( transaction.Guid, scheduledTransaction.AuthorizedPersonAlias.Person.FullName );
                            transaction.FinancialGatewayId = gateway.Id;
                            transaction.TransactionTypeValueId = contributionTxnType.Id;

                            if ( txnAmount < 0.0M )
                            {
                                transaction.Summary = "Reversal for previous transaction that failed during processing." + Environment.NewLine;
                            }

                            var currencyTypeValue = payment.CurrencyTypeValue;
                            var creditCardTypevalue = payment.CreditCardTypeValue;

                            if ( scheduledTransaction.FinancialPaymentDetail != null )
                            {
                                if ( currencyTypeValue == null && scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.HasValue )
                                {
                                    currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.Value );
                                }

                                if ( creditCardTypevalue == null && scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.HasValue )
                                {
                                    creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.Value );
                                }

                                transaction.FinancialPaymentDetail.AccountNumberMasked = scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked;
                                transaction.FinancialPaymentDetail.NameOnCardEncrypted = scheduledTransaction.FinancialPaymentDetail.NameOnCardEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted;
                                transaction.FinancialPaymentDetail.ExpirationYearEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted;
                                transaction.FinancialPaymentDetail.BillingLocationId = scheduledTransaction.FinancialPaymentDetail.BillingLocationId;
                            }

                            if ( currencyTypeValue != null )
                            {
                                transaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeValue.Id;
                            }
                            if ( creditCardTypevalue != null )
                            {
                                transaction.FinancialPaymentDetail.CreditCardTypeValueId = creditCardTypevalue.Id;
                            }

                            // Try to allocate the amount of the transaction based on the current scheduled transaction accounts
                            decimal remainingAmount = Math.Abs( txnAmount );
                            foreach ( var detail in scheduledTransaction.ScheduledTransactionDetails.Where( d => d.Amount != 0.0M ) )
                            {
                                var transactionDetail = new FinancialTransactionDetail();
                                transactionDetail.AccountId = detail.AccountId;

                                if ( detail.Amount <= remainingAmount )
                                {
                                    // If the configured amount for this account is less than or equal to the remaining
                                    // amount, allocate the configured amount
                                    transactionDetail.Amount = detail.Amount;
                                    remainingAmount -= detail.Amount;
                                }
                                else
                                {
                                    // If the configured amount is greater than the remaining amount, only allocate
                                    // the remaining amount
                                    transaction.Summary += "Note: Downloaded transaction amount was less than the configured allocation amounts for the Scheduled Transaction.";
                                    transactionDetail.Amount = remainingAmount;
                                    transactionDetail.Summary = "Note: The downloaded amount was not enough to apply the configured amount to this account.";
                                    remainingAmount = 0.0M;
                                }

                                transaction.TransactionDetails.Add( transactionDetail );

                                if ( remainingAmount <= 0.0M )
                                {
                                    // If there's no amount left, break out of details
                                    break;
                                }
                            }

                            // If there's still amount left after allocating based on current config, add the remainder
                            // to the account that was configured for the most amount
                            if ( remainingAmount > 0.0M )
                            {
                                transaction.Summary += "Note: Downloaded transaction amount was greater than the configured allocation amounts for the Scheduled Transaction.";
                                var transactionDetail = transaction.TransactionDetails
                                    .OrderByDescending( d => d.Amount )
                                    .FirstOrDefault();
                                if ( transactionDetail == null && defaultAccount != null )
                                {
                                    transactionDetail = new FinancialTransactionDetail();
                                    transactionDetail.AccountId = defaultAccount.Id;
                                    transaction.TransactionDetails.Add( transactionDetail );
                                }
                                if ( transactionDetail != null )
                                {
                                    transactionDetail.Amount += remainingAmount;
                                    transactionDetail.Summary = "Note: Extra amount was applied to this account.";
                                }
                            }

                            // If the amount to apply was negative, update all details to be negative (absolute value was used when allocating to accounts)
                            if ( txnAmount < 0.0M )
                            {
                                foreach ( var txnDetail in transaction.TransactionDetails )
                                {
                                    txnDetail.Amount = 0 - txnDetail.Amount;
                                }
                            }

                            // Get the batch
                            var batch = batchService.Get(
                                batchNamePrefix,
                                currencyTypeValue,
                                creditCardTypevalue,
                                transaction.TransactionDateTime.Value,
                                gateway.GetBatchTimeOffset(),
                                batches );

                            var batchChanges = new List<string>();
                            if ( batch.Id != 0 )
                            {
                                initialControlAmounts.AddOrIgnore( batch.Guid, batch.ControlAmount );
                            }
                            batch.ControlAmount += transaction.TotalAmount;

                            batch.Transactions.Add( transaction );

                            if ( txnAmount > 0.0M && receiptEmail.HasValue )
                            {
                                newTransactions.Add( transaction );
                            }

                            // Add summary
                            if ( !batchSummary.ContainsKey( batch.Guid ) )
                            {
                                batchSummary.Add( batch.Guid, new List<Decimal>() );
                            }
                            batchSummary[batch.Guid].Add( txnAmount );

                            if ( txnAmount > 0.0M )
                            {
                                totalAdded++;
                            }
                            else
                            {
                                totalReversals++;
                            }
                        }
                        else
                        {
                            totalAlreadyDownloaded++;

                            foreach ( var txn in txns.Where( t => t.Status != payment.Status || t.StatusMessage != payment.StatusMessage ) )
                            {
                                txn.Status = payment.Status;
                                txn.StatusMessage = payment.StatusMessage;
                                totalStatusChanges++;
                            }
                        }
                    }
                    else
                    {
                        totalNoScheduledTransaction++;
                    }
                }

                rockContext.SaveChanges();

                // Queue a transaction to update the status of all affected scheduled transactions
                var updatePaymentStatusTxn = new Rock.Transactions.UpdatePaymentStatusTransaction( gateway.Id, scheduledTransactionIds );
                Rock.Transactions.RockQueue.TransactionQueue.Enqueue( updatePaymentStatusTxn );

                if ( receiptEmail.HasValue )
                {
                    // Queue a transaction to send receipts
                    var newTransactionIds = newTransactions.Select( t => t.Id ).ToList();
                    var sendPaymentReceiptsTxn = new Rock.Transactions.SendPaymentReceipts( receiptEmail.Value, newTransactionIds );
                    Rock.Transactions.RockQueue.TransactionQueue.Enqueue( sendPaymentReceiptsTxn );
                }
            }

            StringBuilder sb = new StringBuilder();
            sb.AppendFormat( "<li>{0} {1} downloaded.</li>", totalPayments.ToString( "N0" ),
                ( totalPayments == 1 ? "payment" : "payments" ) );

            if ( totalAlreadyDownloaded > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} previously downloaded and {2} already been added.</li>", totalAlreadyDownloaded.ToString( "N0" ),
                    ( totalAlreadyDownloaded == 1 ? "payment was" : "payments were" ),
                    ( totalAlreadyDownloaded == 1 ? "has" : "have" ) );
            }

            if ( totalStatusChanges > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} previously downloaded but had a change of status.</li>", totalStatusChanges.ToString( "N0" ),
                ( totalStatusChanges == 1 ? "payment was" : "payments were" ) );
            }

            if ( totalNoScheduledTransaction > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} could not be matched to an existing scheduled payment profile.</li>", totalNoScheduledTransaction.ToString( "N0" ),
                    ( totalNoScheduledTransaction == 1 ? "payment" : "payments" ) );
            }

            sb.AppendFormat( "<li>{0} {1} successfully added.</li>", totalAdded.ToString( "N0" ),
                ( totalAdded == 1 ? "payment was" : "payments were" ) );

            if ( totalReversals > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} added as a reversal to a previous transaction.</li>", totalReversals.ToString( "N0" ),
                    ( totalReversals == 1 ? "payment was" : "payments were" ) );
            }

            if ( totalStatusChanges > 0 )
            {
                sb.AppendFormat( "<li>{0} {1} previously downloaded but had a change of status.</li>", totalStatusChanges.ToString( "N0" ),
                    ( totalStatusChanges == 1 ? "payment was" : "payments were" ) );
            }

            foreach ( var batchItem in batchSummary )
            {
                int items = batchItem.Value.Count;
                if ( items > 0 )
                {
                    var batch = batches
                        .Where( b => b.Guid.Equals( batchItem.Key ) )
                        .FirstOrDefault();

                    string batchName = string.Format( "'{0} ({1})'", batch.Name, batch.BatchStartDateTime.Value.ToString( "d" ) );
                    if ( !string.IsNullOrWhiteSpace( batchUrlFormat ) )
                    {
                        batchName = string.Format( "<a href='{0}'>{1}</a>", string.Format( batchUrlFormat, batch.Id ), batchName );
                    }

                    decimal sum = batchItem.Value.Sum();

                    string summaryformat = items == 1 ?
                        "<li>{0} transaction of {1} was added to the {2} batch.</li>" :
                        "<li>{0} transactions totaling {1} were added to the {2} batch</li>";

                    sb.AppendFormat( summaryformat, items.ToString( "N0" ), sum.FormatAsCurrency(), batchName );
                }
            }

            return sb.ToString();
        }
        /// <summary>
        /// Handles the Click event of the lbSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void lbSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();

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

            FinancialTransaction txn = null;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    rockContext.SaveChanges();

                } );

                // Requery the batch to support EF navigation properties
                var savedTxn = GetTransaction( txn.Id );
                ShowReadOnlyDetails( savedTxn );
            }
        }
Exemple #49
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 ) );
        }
        /// <summary>
        /// Shows the read only details.
        /// </summary>
        /// <param name="txn">The TXN.</param>
        private void ShowReadOnlyDetails( FinancialTransaction txn )
        {
            SetEditMode( false );

            if ( txn != null )
            {
                hfTransactionId.Value = txn.Id.ToString();

                SetHeadingInfo( txn );

                string rockUrlRoot = ResolveRockUrl( "/" );

                var detailsLeft = new DescriptionList()
                    .Add( "Person", txn.AuthorizedPerson != null ? txn.AuthorizedPerson.GetAnchorTag( rockUrlRoot ) : string.Empty )
                    .Add( "Amount", ( txn.TransactionDetails.Sum( d => (decimal?)d.Amount ) ?? 0.0M ).ToString( "C2" ) )
                    .Add( "Date/Time", txn.TransactionDateTime.HasValue ? txn.TransactionDateTime.Value.ToString( "g" ) : string.Empty );

                if ( txn.Batch != null )
                {
                    var qryParam = new Dictionary<string, string>();
                    qryParam.Add( "BatchId", txn.Batch.Id.ToString() );
                    string url = LinkedPageUrl( "BatchDetailPage", qryParam );
                    detailsLeft.Add( "Batch", !string.IsNullOrWhiteSpace( url ) ?
                        string.Format( "<a href='{0}'>{1}</a>", url, txn.Batch.Name ) :
                        txn.Batch.Name );
                }

                detailsLeft.Add( "Source", txn.SourceTypeValue != null ? txn.SourceTypeValue.Value : string.Empty );

                if ( txn.GatewayEntityType != null )
                {
                    detailsLeft.Add( "Payment Gateway", Rock.Financial.GatewayContainer.GetComponentName( txn.GatewayEntityType.Name ) );
                }

                detailsLeft.Add( "Transaction Code", txn.TransactionCode );

                if ( txn.ScheduledTransaction != null )
                {
                    var qryParam = new Dictionary<string, string>();
                    qryParam.Add( "ScheduledTransactionId", txn.ScheduledTransaction.Id.ToString() );
                    string url = LinkedPageUrl( "ScheduledTransactionDetailPage", qryParam );
                    detailsLeft.Add( "Scheduled Transaction Id", !string.IsNullOrWhiteSpace( url ) ?
                        string.Format( "<a href='{0}'>{1}</a>", url, txn.ScheduledTransaction.GatewayScheduleId ) :
                        txn.ScheduledTransaction.GatewayScheduleId );
                }

                if ( txn.CurrencyTypeValue != null )
                {
                    string currencyType = txn.CurrencyTypeValue.Value;
                    if ( txn.CurrencyTypeValue.Guid.Equals( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD.AsGuid() ) )
                    {
                        currencyType += txn.CreditCardTypeValue != null ? ( " - " + txn.CreditCardTypeValue.Value ) : string.Empty;
                    }
                    detailsLeft.Add( "Currency Type", currencyType );
                }

                detailsLeft.Add( "Summary", txn.Summary );

                var modified = new StringBuilder(); ;
                if ( txn.CreatedByPersonAlias != null && txn.CreatedByPersonAlias.Person != null && txn.CreatedDateTime.HasValue )
                {
                    modified.AppendFormat( "Created by {0} on {1} at {2}<br/>", txn.CreatedByPersonAlias.Person.GetAnchorTag( rockUrlRoot ),
                        txn.CreatedDateTime.Value.ToShortDateString(), txn.CreatedDateTime.Value.ToShortTimeString() );
                }
                if ( txn.ProcessedByPersonAlias != null && txn.ProcessedByPersonAlias.Person != null && txn.ProcessedDateTime.HasValue )
                {
                    modified.AppendFormat( "Processed by {0} on {1} at {2}<br/>", txn.ProcessedByPersonAlias.Person.GetAnchorTag( rockUrlRoot ),
                        txn.ProcessedDateTime.Value.ToShortDateString(), txn.ProcessedDateTime.Value.ToShortTimeString() );
                }
                if ( txn.ModifiedByPersonAlias != null && txn.ModifiedByPersonAlias.Person != null && txn.ModifiedDateTime.HasValue )
                {
                    modified.AppendFormat( "Last Modified by {0} on {1} at {2}<br/>", txn.ModifiedByPersonAlias.Person.GetAnchorTag( rockUrlRoot ),
                        txn.ModifiedDateTime.Value.ToShortDateString(), txn.ModifiedDateTime.Value.ToShortTimeString() );
                }
                detailsLeft.Add( "Updates", modified.ToString() );

                lDetailsLeft.Text = detailsLeft.Html;

                gAccountsView.DataSource = txn.TransactionDetails.ToList();
                gAccountsView.DataBind();

                if ( txn.Images.Any() )
                {
                    var primaryImage = txn.Images
                        .OrderBy( i => i.TransactionImageTypeValue.Order )
                        .FirstOrDefault();
                    imgPrimary.ImageUrl = string.Format( "~/GetImage.ashx?id={0}", primaryImage.BinaryFileId );
                    imgPrimary.Visible = true;

                    rptrImages.DataSource = txn.Images
                        .Where( i => !i.Id.Equals( primaryImage.Id ) )
                        .OrderBy( i => i.TransactionImageTypeValue.Order )
                        .ToList();
                    rptrImages.DataBind();
                }
                else
                {
                    imgPrimary.Visible = false;
                }
            }
        }
        /// <summary>
        /// Shows the edit details.
        /// </summary>
        /// <param name="txn">The TXN.</param>
        private void ShowEditDetails( FinancialTransaction txn, RockContext rockContext )
        {
            if ( txn != null )
            {
                BindDropdowns( rockContext );

                hfTransactionId.Value = txn.Id.ToString();

                SetHeadingInfo( txn );

                SetEditMode( true );

                ppAuthorizedPerson.SetValue( txn.AuthorizedPerson );
                dtTransactionDateTime.SelectedDateTime = txn.TransactionDateTime;
                ddlTransactionType.SetValue( txn.TransactionTypeValueId );
                ddlSourceType.SetValue( txn.SourceTypeValueId );
                cpPaymentGateway.SetValue( txn.GatewayEntityType != null ? txn.GatewayEntityType.Guid.ToString().ToUpper() : string.Empty );
                tbTransactionCode.Text = txn.TransactionCode;
                ddlCurrencyType.SetValue( txn.CurrencyTypeValueId );
                ddlCreditCardType.SetValue( txn.CreditCardTypeValueId );
                SetCreditCardVisibility();

                TransactionDetailsState = txn.TransactionDetails.ToList();
                TransactionImagesState = txn.Images.ToList();

                BindAccountsEditGrid();
                tbSummary.Text = txn.Summary;

                BinaryFileIds = txn.Images.Select( i => i.BinaryFileId ).ToList();

                BindImages();
            }
        }
 /// <summary>
 /// Sets the heading information.
 /// </summary>
 /// <param name="txn">The TXN.</param>
 private void SetHeadingInfo( FinancialTransaction txn )
 {
     if ( txn.TransactionTypeValue != null )
     {
         hlType.Visible = true;
         hlType.Text = txn.TransactionTypeValue.Value;
     }
     else
     {
         hlType.Visible = false;
     }
 }
        private void SaveTransaction( FinancialGateway financialGateway, GatewayComponent gateway, Person person, PaymentInfo paymentInfo, FinancialTransaction transaction, RockContext rockContext )
        {
            var txnChanges = new List<string>();
            txnChanges.Add( "Created Transaction" );

            History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode );

            transaction.AuthorizedPersonAliasId = person.PrimaryAliasId;
            History.EvaluateChange( txnChanges, "Person", string.Empty, person.FullName );

            transaction.TransactionDateTime = RockDateTime.Now;
            History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime );

            transaction.FinancialGatewayId = financialGateway.Id;
            History.EvaluateChange( txnChanges, "Gateway", string.Empty, financialGateway.Name );

            var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ) );
            transaction.TransactionTypeValueId = txnType.Id;
            History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value );

            transaction.Summary = paymentInfo.Comment1;
            History.EvaluateChange( txnChanges, "Summary", string.Empty, transaction.Summary );

            if ( transaction.FinancialPaymentDetail == null )
            {
                transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
            }
            transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges );

            Guid sourceGuid = Guid.Empty;
            if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) )
            {
                var source = DefinedValueCache.Read( sourceGuid );
                if ( source != null )
                {
                    transaction.SourceTypeValueId = source.Id;
                    History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value );
                }
            }

            foreach ( var account in SelectedAccounts.Where( a => a.Amount > 0 ) )
            {
                var transactionDetail = new FinancialTransactionDetail();
                transactionDetail.Amount = account.Amount;
                transactionDetail.AccountId = account.Id;
                transaction.TransactionDetails.Add( transactionDetail );
                History.EvaluateChange( txnChanges, account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() );
            }

            var batchService = new FinancialBatchService( rockContext );

            // Get the batch
            var batch = batchService.Get(
                GetAttributeValue( "BatchNamePrefix" ),
                paymentInfo.CurrencyTypeValue,
                paymentInfo.CreditCardTypeValue,
                transaction.TransactionDateTime.Value,
                financialGateway.GetBatchTimeOffset() );

            var batchChanges = new List<string>();

            if ( batch.Id == 0 )
            {
                batchChanges.Add( "Generated the batch" );
                History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name );
                History.EvaluateChange( batchChanges, "Status", null, batch.Status );
                History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime );
                History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime );
            }

            decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount;
            History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() );
            batch.ControlAmount = newControlAmount;

            transaction.BatchId = batch.Id;
            batch.Transactions.Add( transaction );

            rockContext.SaveChanges();

            HistoryService.SaveChanges(
                rockContext,
                typeof( FinancialBatch ),
                Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                batch.Id,
                batchChanges
            );

            HistoryService.SaveChanges(
                rockContext,
                typeof( FinancialBatch ),
                Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                batch.Id,
                txnChanges,
                person.FullName,
                typeof( FinancialTransaction ),
                transaction.Id
            );

            SendReceipt( transaction.Id );

            TransactionCode = transaction.TransactionCode;
        }
        /// <summary>
        /// Handles the Click event of the lbSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void lbSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();

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

            FinancialTransaction txn = null;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    rockContext.SaveChanges();

                } );

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

                // Requery the batch to support EF navigation properties
                var savedTxn = GetTransaction( txn.Id );
                ShowReadOnlyDetails( savedTxn );
            }
        }
        /// <summary>
        /// Formats the summary.
        /// </summary>
        /// <param name="txn">The TXN.</param>
        /// <returns></returns>
        private string FormatSummary( FinancialTransaction txn )
        {
            var sb = new StringBuilder();
            foreach ( var transactionDetail in txn.TransactionDetails )
            {
                sb.AppendFormat( "{0} ({2}{1})<br>", transactionDetail.Account, transactionDetail.Amount, GlobalAttributesCache.Value( "CurrencySymbol" ) );
            }

            return sb.ToString();
        }
        /// <summary>
        /// Shows the edit details.
        /// </summary>
        /// <param name="txn">The TXN.</param>
        private void ShowEditDetails( FinancialTransaction txn, RockContext rockContext )
        {
            this.Page.ClientScript.RegisterStartupScript(
                this.GetType(),
                "StartupScript", @"Sys.Application.add_load(function () {

                // if the person picker is empty then open it for quick entry
                var personPicker = $('.js-authorizedperson');
                var currentPerson = personPicker.find('.picker-selectedperson').html();
                if (currentPerson != null && currentPerson.length == 0) {
                    $(personPicker).find('a.picker-label').trigger('click');
                }

            });", true );

            if ( txn != null )
            {
                BindDropdowns( rockContext );

                hfTransactionId.Value = txn.Id.ToString();

                SetHeadingInfo( txn );

                SetEditMode( true );

                if ( txn.AuthorizedPersonAlias != null )
                {
                    ppAuthorizedPerson.SetValue( txn.AuthorizedPersonAlias.Person );
                }
                else
                {
                    ppAuthorizedPerson.SetValue( null );
                }
                dtTransactionDateTime.SelectedDateTime = txn.TransactionDateTime;
                ddlTransactionType.SetValue( txn.TransactionTypeValueId );
                ddlSourceType.SetValue( txn.SourceTypeValueId );
                cpPaymentGateway.SetValue( txn.GatewayEntityType != null ? txn.GatewayEntityType.Guid.ToString().ToUpper() : string.Empty );
                tbTransactionCode.Text = txn.TransactionCode;
                ddlCurrencyType.SetValue( txn.CurrencyTypeValueId );
                ddlCreditCardType.SetValue( txn.CreditCardTypeValueId );
                SetCreditCardVisibility();

                TransactionDetailsState = txn.TransactionDetails.ToList();
                TransactionImagesState = txn.Images.OrderBy( i => i.Order ).Select( i => i.BinaryFileId ).ToList();

                if ( TransactionDetailsState.Count() == 1 )
                {
                    UseSimpleAccountMode = true;
                }
                else
                {
                    UseSimpleAccountMode = false;
                }
                BindAccounts();

                tbSummary.Text = txn.Summary;

                BindImages();
            }
        }
Exemple #57
0
        /// <summary>
        /// Charges the specified payment info.
        /// </summary>
        /// <param name="paymentInfo">The payment info.</param>
        /// <param name="errorMessage">The error message.</param>
        /// <returns></returns>
        public override FinancialTransaction Charge( FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage )
        {
            errorMessage = string.Empty;
            RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo );
            if ( request == null )
            {
                errorMessage = "Payment type not implemented";
                return null;
            }

            request.purchaseTotals = GetTotals();
            request.billTo = GetBillTo( paymentInfo );
            request.item = GetItems( paymentInfo );

            if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) )
            {
                request.ecDebitService = new ECDebitService();
                request.ecDebitService.commerceIndicator = "internet";
                request.ecDebitService.run = "true";
            }
            else
            {
                request.ccAuthService = new CCAuthService();
                request.ccAuthService.commerceIndicator = "internet";
                request.ccAuthService.run = "true";
                request.ccCaptureService = new CCCaptureService();
                request.ccCaptureService.run = "true";
            }

            // Charge the transaction
            ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage );
            if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) )
            {
                var transactionGuid = new Guid( reply.merchantReferenceCode );
                var transaction = new FinancialTransaction { Guid = transactionGuid };
                transaction.TransactionCode = reply.requestID;
                return transaction;
            }
            else if ( string.IsNullOrEmpty( errorMessage ) )
            {
                errorMessage = string.Format( "Unable to process this order.{0}", ProcessError( reply ) );
            }

            return null;
        }
        /// <summary>
        /// Shows the detail.
        /// </summary>
        /// <param name="transactionId">The transaction identifier.</param>
        public void ShowDetail( int transactionId, int? batchId )
        {
            // show or hide the add new transaction button depending if there is a batch id in the querystring
            lbAddTransaction.Visible = !string.IsNullOrWhiteSpace( PageParameter( "batchId" ) );

            FinancialTransaction txn = null;

            bool editAllowed = UserCanEdit;

            var rockContext = new RockContext();

            if ( !transactionId.Equals( 0 ) )
            {
                txn = GetTransaction( transactionId, rockContext );
                if ( !editAllowed && txn != null )
                {
                    editAllowed = txn.IsAuthorized( Authorization.EDIT, CurrentPerson );
                }
            }

            if ( txn == null )
            {
                txn = new FinancialTransaction { Id = 0 };
                txn.BatchId = batchId;

                // Hide processor fields when adding a new transaction
                cpPaymentGateway.Visible = false;
                tbTransactionCode.Visible = false;

                // Set values based on previously saved txn values
                int prevBatchId = Session["NewTxnDefault_BatchId"] as int? ?? 0;
                if ( prevBatchId == batchId )
                {
                    txn.TransactionDateTime = Session["NewTxnDefault_TransactionDateTime"] as DateTime?;
                    txn.TransactionTypeValueId = Session["NewTxnDefault_TransactionType"] as int? ?? 0;
                    txn.SourceTypeValueId = Session["NewTxnDefault_SourceType"] as int?;
                    txn.CurrencyTypeValueId = Session["NewTxnDefault_CurrencyType"] as int?;
                    txn.CreditCardTypeValueId = Session["NewTxnDefault_CreditCardType"] as int?;
                    int? accountId = Session["NewTxnDefault_Account"] as int?;
                    if ( accountId.HasValue )
                    {
                        var txnDetail = new FinancialTransactionDetail();
                        txnDetail.AccountId = accountId.Value;
                        txn.TransactionDetails.Add( txnDetail );
                    }
                }
            }
            else
            {
                cpPaymentGateway.Visible = true;
                tbTransactionCode.Visible = true;
            }

            hfTransactionId.Value = txn.Id.ToString();
            hfBatchId.Value = batchId.HasValue ? batchId.Value.ToString() : string.Empty;

            bool readOnly = false;

            nbEditModeMessage.Text = string.Empty;
            if ( !editAllowed )
            {
                readOnly = true;
                nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( FinancialTransaction.FriendlyTypeName );
                lbEdit.Visible = false;
                lbAddTransaction.Visible = false;
            }
            else
            {
                lbEdit.Visible = true;
                lbAddTransaction.Visible = true;
            }

            if ( readOnly )
            {
                ShowReadOnlyDetails( txn );
            }
            else
            {
                if ( txn.Id > 0 )
                {
                    ShowReadOnlyDetails( txn );
                }
                else
                {
                    ShowEditDetails( txn, rockContext );
                }
            }

            lbSave.Visible = !readOnly;
        }
        private void LaunchWorkflow( WorkflowType workflowType, FinancialTransaction transaction )
        {
            if ( workflowType != null )
            {
                using ( var rockContext = new RockContext() )
                {
                    string workflowName = transaction.TransactionCode;
                    if ( transaction.AuthorizedPersonAliasId != null )
                    {
                        var person = new PersonAliasService( rockContext ).GetPerson( transaction.AuthorizedPersonAliasId.Value );
                        if ( person != null )
                        {
                            workflowName = person.FullName;
                        }
                    }

                    var workflowService = new WorkflowService( rockContext );
                    var workflow = Rock.Model.Workflow.Activate( workflowType, workflowName, rockContext );
                    if ( workflow != null )
                    {
                        List<string> workflowErrors;
                        workflowService.Process( workflow, transaction, out workflowErrors );
                    }
                }
            }
        }
        private bool SaveTransaction( GatewayComponent gateway, Registration registration, FinancialTransaction transaction, PaymentInfo paymentInfo, RockContext rockContext )
        {
            if ( transaction != null )
            {
                var txnChanges = new List<string>();
                txnChanges.Add( "Created Transaction" );

                History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode );

                transaction.AuthorizedPersonAliasId = registration.PersonAliasId;

                transaction.TransactionDateTime = RockDateTime.Now;
                History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime );

                transaction.FinancialGatewayId = RegistrationTemplate.FinancialGatewayId;
                History.EvaluateChange( txnChanges, "Gateway", string.Empty, RegistrationTemplate.FinancialGateway.Name );

                var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_EVENT_REGISTRATION ) );
                transaction.TransactionTypeValueId = txnType.Id;
                History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value );

                if ( transaction.FinancialPaymentDetail == null )
                {
                    transaction.FinancialPaymentDetail = new FinancialPaymentDetail();
                }

                DefinedValueCache currencyType = null;
                DefinedValueCache creditCardType = null;

                if ( paymentInfo != null )
                {
                    transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges );
                    currencyType = paymentInfo.CurrencyTypeValue;
                    creditCardType = paymentInfo.CreditCardTypeValue;
                }

                Guid sourceGuid = Guid.Empty;
                if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) )
                {
                    var source = DefinedValueCache.Read( sourceGuid );
                    if ( source != null )
                    {
                        transaction.SourceTypeValueId = source.Id;
                        History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value );
                    }
                }

                transaction.Summary = registration.GetSummary( RegistrationInstanceState );

                var transactionDetail = new FinancialTransactionDetail();
                transactionDetail.Amount = RegistrationState.PaymentAmount ?? 0.0m;
                transactionDetail.AccountId = RegistrationInstanceState.AccountId.Value;
                transactionDetail.EntityTypeId = EntityTypeCache.Read( typeof( Rock.Model.Registration ) ).Id;
                transactionDetail.EntityId = registration.Id;
                transaction.TransactionDetails.Add( transactionDetail );

                History.EvaluateChange( txnChanges, RegistrationInstanceState.Account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() );

                var batchChanges = new List<string>();

                rockContext.WrapTransaction( () =>
                {
                    var batchService = new FinancialBatchService( rockContext );

                    // determine batch prefix
                    string batchPrefix = string.Empty;
                    if ( !string.IsNullOrWhiteSpace( RegistrationTemplate.BatchNamePrefix ) )
                    {
                        batchPrefix = RegistrationTemplate.BatchNamePrefix;
                    }
                    else
                    {
                        batchPrefix = GetAttributeValue( "BatchNamePrefix" );
                    }

                    // Get the batch
                    var batch = batchService.Get(
                        batchPrefix,
                        currencyType,
                        creditCardType,
                        transaction.TransactionDateTime.Value,
                        RegistrationTemplate.FinancialGateway.GetBatchTimeOffset() );

                    if ( batch.Id == 0 )
                    {
                        batchChanges.Add( "Generated the batch" );
                        History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name );
                        History.EvaluateChange( batchChanges, "Status", null, batch.Status );
                        History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime );
                        History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime );
                    }

                    decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount;
                    History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() );
                    batch.ControlAmount = newControlAmount;

                    transaction.BatchId = batch.Id;
                    batch.Transactions.Add( transaction );

                    rockContext.SaveChanges();
                } );

                if ( transaction.BatchId.HasValue )
                {
                    Task.Run( () =>
                        HistoryService.SaveChanges(
                            new RockContext(),
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                            transaction.BatchId.Value,
                            batchChanges, true, CurrentPersonAliasId )
                    );

                    Task.Run( () =>
                        HistoryService.SaveChanges(
                            new RockContext(),
                            typeof( FinancialBatch ),
                            Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(),
                            transaction.BatchId.Value,
                            txnChanges,
                            CurrentPerson != null ? CurrentPerson.FullName : string.Empty,
                            typeof( FinancialTransaction ),
                            transaction.Id, true, CurrentPersonAliasId )
                    );
                }

                List<string> registrationChanges = new List<string>();
                registrationChanges.Add( string.Format( "Made {0} payment", transaction.TotalAmount.FormatAsCurrency() ) );
                Task.Run( () =>
                    HistoryService.SaveChanges(
                        new RockContext(),
                        typeof( Registration ),
                        Rock.SystemGuid.Category.HISTORY_EVENT_REGISTRATION.AsGuid(),
                        registration.Id,
                        registrationChanges, true, CurrentPersonAliasId )
                );

                TransactionCode = transaction.TransactionCode;

                return true;
            }
            else
            {
                return false;
            }
        }