Example #1
0
        /// <summary>
        /// This method stores the transaction in the database along with the appropriate details and batch information.
        /// </summary>
        private FinancialTransaction SaveTransaction(Guid transactionGuid)
        {
            // if this is a future transaction, the payment hasn't been charged yet
            if (_payment == null && _automatedPaymentArgs.FutureProcessingDateTime.HasValue)
            {
                _payment = new Payment
                {
                    Status          = "PreProcessing",
                    StatusMessage   = "This transaction is scheduled to be processed in the future",
                    TransactionCode = _financialPersonSavedAccount.Id.ToStringSafe()
                };
            }

            // Create a new transaction or update the future transaction now that it has been charged
            var financialTransaction = _futureTransaction ?? new FinancialTransaction();

            financialTransaction.TransactionCode          = _payment.TransactionCode;
            financialTransaction.Guid                     = transactionGuid;
            financialTransaction.CreatedByPersonAliasId   = _currentPersonAliasId;
            financialTransaction.ScheduledTransactionId   = _automatedPaymentArgs.ScheduledTransactionId;
            financialTransaction.AuthorizedPersonAliasId  = _automatedPaymentArgs.AuthorizedPersonAliasId;
            financialTransaction.ShowAsAnonymous          = _automatedPaymentArgs.ShowAsAnonymous;
            financialTransaction.TransactionDateTime      = _automatedPaymentArgs.FutureProcessingDateTime.HasValue ? ( DateTime? )null : RockDateTime.Now;
            financialTransaction.FinancialGatewayId       = _financialGateway.Id;
            financialTransaction.TransactionTypeValueId   = _transactionType.Id;
            financialTransaction.Summary                  = string.Format("{0} {1}", financialTransaction.Summary, _referencePaymentInfo.Comment1).Trim();
            financialTransaction.SourceTypeValueId        = _financialSource.Id;
            financialTransaction.IsSettled                = _payment.IsSettled;
            financialTransaction.Status                   = _payment.Status;
            financialTransaction.StatusMessage            = _payment.StatusMessage;
            financialTransaction.SettledDate              = _payment.SettledDate;
            financialTransaction.ForeignKey               = _payment.ForeignKey;
            financialTransaction.FutureProcessingDateTime = _automatedPaymentArgs.FutureProcessingDateTime;


            financialTransaction.ForeignCurrencyCodeValueId = GetCurrencyCodeDefinedValueCache(_automatedPaymentArgs.AmountCurrencyCode)?.Id;

            // Create a new payment detail or update the future transaction's payment detail now that it has been charged
            var financialPaymentDetail = financialTransaction.FinancialPaymentDetail ?? new FinancialPaymentDetail();

            financialPaymentDetail.AccountNumberMasked           = _payment.AccountNumberMasked;
            financialPaymentDetail.NameOnCard                    = _payment.NameOnCard;
            financialPaymentDetail.ExpirationMonth               = _payment.ExpirationMonth;
            financialPaymentDetail.ExpirationYear                = _payment.ExpirationYear;
            financialPaymentDetail.CreatedByPersonAliasId        = _currentPersonAliasId;
            financialPaymentDetail.ForeignKey                    = _payment.ForeignKey;
            financialPaymentDetail.GatewayPersonIdentifier       = _financialPersonSavedAccount?.GatewayPersonIdentifier;
            financialPaymentDetail.FinancialPersonSavedAccountId = _financialPersonSavedAccount?.Id;

            if (_payment.CurrencyTypeValue != null)
            {
                financialPaymentDetail.CurrencyTypeValueId = _payment.CurrencyTypeValue.Id;
            }

            if (_payment.CreditCardTypeValue != null)
            {
                financialPaymentDetail.CreditCardTypeValueId = _payment.CreditCardTypeValue.Id;
            }

            financialPaymentDetail.SetFromPaymentInfo(_referencePaymentInfo, _automatedGatewayComponent, _rockContext);
            financialTransaction.FinancialPaymentDetail   = financialPaymentDetail;
            financialTransaction.FinancialPaymentDetailId = financialPaymentDetail.Id == 0 ? ( int? )null : financialPaymentDetail.Id;

            // Future transactions already have the appropriate FinancialTransactionDetail models
            if (_futureTransaction == null)
            {
                var doesHaveForeignCurrency = financialTransaction.ForeignCurrencyCodeValueId != null;

                foreach (var detailArgs in _automatedPaymentArgs.AutomatedPaymentDetails)
                {
                    var transactionDetail = new FinancialTransactionDetail
                    {
                        Amount    = detailArgs.Amount,
                        AccountId = detailArgs.AccountId
                    };

                    if (doesHaveForeignCurrency)
                    {
                        transactionDetail.ForeignCurrencyAmount = detailArgs.Amount;
                    }

                    financialTransaction.TransactionDetails.Add(transactionDetail);
                }

                if (doesHaveForeignCurrency)
                {
                    /*
                     * The amount coming from the gateway is always in the Organization's currency.
                     * As such the Amount value could be different than the original amount passed in if the
                     * specified currency code is different then the Organization's currency code.
                     */
                    financialTransaction.SetApportionedDetailAmounts(_payment.Amount);
                }
            }

            // New transactions and future transactions need fee info
            financialTransaction.SetApportionedFeesOnDetails(_payment.FeeAmount);

            // Get an existing or new batch according to the name prefix and payment type
            FinancialBatch batch;

            if (!financialTransaction.BatchId.HasValue)
            {
                batch = _financialBatchService.Get(
                    _automatedPaymentArgs.BatchNamePrefix ?? "Online Giving",
                    string.Empty,
                    _referencePaymentInfo.CurrencyTypeValue,
                    _referencePaymentInfo.CreditCardTypeValue,
                    financialTransaction.TransactionDateTime ?? financialTransaction.FutureProcessingDateTime.Value,
                    _financialGateway.GetBatchTimeOffset(),
                    _financialGateway.BatchDayOfWeek);
            }
            else
            {
                batch = _financialBatchService.Get(financialTransaction.BatchId.Value);
            }

            var batchChanges = new History.HistoryChangeList();
            var isNewBatch   = batch.Id == 0;

            // If this is a new Batch, SaveChanges so that we can get the Batch.Id and also
            // add history entries about the batch creation
            if (isNewBatch)
            {
                batchChanges.AddChange(History.HistoryVerb.Add, History.HistoryChangeType.Record, "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);

                _rockContext.SaveChanges();
            }

            if (_futureTransaction == null)
            {
                // Use the financialTransactionService to add the transaction instead of batch.Transactions
                // to avoid lazy-loading the transactions already associated with the batch
                financialTransaction.BatchId = batch.Id;
                _financialTransactionService.Add(financialTransaction);
            }

            _rockContext.SaveChanges();

            if (_futureTransaction == null)
            {
                // Update the batch control amount
                _financialBatchService.IncrementControlAmount(batch.Id, financialTransaction.TotalAmount, batchChanges);
                _rockContext.SaveChanges();
            }

            // Save the changes history for the batch
            HistoryService.SaveChanges(
                _rockContext,
                typeof(FinancialBatch),
                SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(),
                batch.Id,
                batchChanges
                );

            return(financialTransaction);
        }