Пример #1
0
        public void FinancialTransactionDateKeyJoinsCorrectly()
        {
            var expectedRecordCount = 15;
            var transactionYear     = 2015;
            var settledYear         = 2016;

            using (var rockContext = new RockContext())
            {
                var financialTransactionService = new FinancialTransactionService(rockContext);

                var minTransactionDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, transactionYear);
                var maxTransactionDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, transactionYear);

                var minSettledDateValue = TestDataHelper.GetAnalyticsSourceMinDateForYear(rockContext, settledYear);
                var maxSettledDateValue = TestDataHelper.GetAnalyticsSourceMaxDateForYear(rockContext, settledYear);



                for (var i = 0; i < 15; i++)
                {
                    var financialTransaction = BuildFinancialTransaction(rockContext,
                                                                         TestDataHelper.GetRandomDateInRange(minTransactionDateValue, maxTransactionDateValue),
                                                                         TestDataHelper.GetRandomDateInRange(minSettledDateValue, maxSettledDateValue));

                    financialTransactionService.Add(financialTransaction);
                }

                rockContext.SaveChanges();
            }

            using (var rockContext = new RockContext())
            {
                var financialTransactionService = new FinancialTransactionService(rockContext);

                var financialTransactions = financialTransactionService.
                                            Queryable().
                                            Where(i => i.ForeignKey == financialTransactionForeignKey).
                                            Where(i => i.TransactionSourceDate.CalendarYear == transactionYear);

                Assert.AreEqual(expectedRecordCount, financialTransactions.Count());
                Assert.IsNotNull(financialTransactions.First().TransactionSourceDate);

                financialTransactions = financialTransactionService.
                                        Queryable().
                                        Where(i => i.ForeignKey == financialTransactionForeignKey).
                                        Where(i => i.SettledSourceDate.CalendarYear == settledYear);

                Assert.AreEqual(expectedRecordCount, financialTransactions.Count());
                Assert.IsNotNull(financialTransactions.First().SettledSourceDate);
            }
        }
Пример #2
0
        public void RockCleanup_Execute_ShouldUpdatePeopleWithFinancialTransactionToAccountProtectionProfileHigh()
        {
            var personGuid = Guid.NewGuid();
            var personWithFinancialTransaction = new Person
            {
                FirstName = "Test",
                LastName  = personGuid.ToString(),
                Email     = $"{personGuid}@test.com",
                Guid      = personGuid
            };

            using (var rockContext = new RockContext())
            {
                var personService = new PersonService(rockContext);
                personService.Add(personWithFinancialTransaction);
                rockContext.SaveChanges();

                personWithFinancialTransaction = personService.Get(personWithFinancialTransaction.Id);

                var financialScheduledTransaction = new FinancialTransaction
                {
                    AuthorizedPersonAliasId = personWithFinancialTransaction.PrimaryAliasId.Value,
                    TransactionTypeValueId  = DefinedValueCache.Get(SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid()).Id
                };

                var service = new FinancialTransactionService(rockContext);
                service.Add(financialScheduledTransaction);
                rockContext.SaveChanges();
            }

            ExecuteRockCleanupJob();

            using (var rockContext = new RockContext())
            {
                var actualPerson = new PersonService(rockContext).Get(personGuid);
                Assert.That.AreEqual(AccountProtectionProfile.High, actualPerson.AccountProtectionProfile);
            }
        }
Пример #3
0
        public void FinancialTransactionDateKeySavesCorrectly()
        {
            var rockContext = new RockContext();
            var financialTransactionService = new FinancialTransactionService(rockContext);

            var financialTransaction = BuildFinancialTransaction(rockContext, Convert.ToDateTime("3/15/2010"), Convert.ToDateTime("3/16/2010"));

            financialTransactionService.Add(financialTransaction);
            rockContext.SaveChanges();

            var financialTransactionId = financialTransaction.Id;

            // We're bypassing the model because the model doesn't user the FinancialTransactionDateKey from the database,
            // but it still needs to be correct for inner joins to work correctly.
            var result = rockContext.Database.
                         SqlQuery <int>($"SELECT TransactionDateKey FROM FinancialTransaction WHERE Id = {financialTransactionId}").First();

            Assert.AreEqual(20100315, result);

            result = rockContext.Database.
                     SqlQuery <int>($"SELECT SettledDateKey FROM FinancialTransaction WHERE Id = {financialTransactionId}").First();

            Assert.AreEqual(20100316, result);
        }
Пример #4
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);
        }
Пример #5
0
        /// <summary>
        /// Handles the Click event of the btnGive 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 btnGive_Click(object sender, EventArgs e)
        {
            Person person = FindPerson();

            using (new UnitOfWorkScope())
            {
                RockTransactionScope.WrapTransaction(() =>
                {
                    var groupLocationService = new GroupLocationService();
                    var groupMemberService   = new GroupMemberService();
                    var phoneService         = new PhoneNumberService();
                    var locationService      = new LocationService();
                    var groupService         = new GroupService();
                    GroupLocation groupLocation;
                    Location homeAddress;
                    Group familyGroup;

                    var homeLocationType = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.LOCATION_TYPE_HOME);
                    var addressList      = locationService.Queryable().Where(l => l.Street1 == txtStreet.Text &&
                                                                             l.City == txtCity.Text && l.State == ddlState.SelectedValue && l.Zip == txtZip.Text &&
                                                                             l.LocationTypeValueId == homeLocationType.Id).ToList();

                    if (!addressList.Any())
                    {
                        homeAddress = new Location();
                        locationService.Add(homeAddress, person.Id);
                    }
                    else
                    {
                        homeAddress = addressList.FirstOrDefault();
                    }

                    homeAddress.Street1             = txtStreet.Text ?? homeAddress.Street1;
                    homeAddress.City                = txtCity.Text ?? homeAddress.City;
                    homeAddress.State               = ddlState.SelectedValue ?? homeAddress.State;
                    homeAddress.Zip                 = txtZip.Text ?? homeAddress.Zip;
                    homeAddress.IsActive            = true;
                    homeAddress.IsLocation          = true;
                    homeAddress.Country             = "US";
                    homeAddress.LocationTypeValueId = homeLocationType.Id;
                    locationService.Save(homeAddress, person.Id);

                    GroupType familyGroupType = new GroupTypeService().Get(new Guid(Rock.SystemGuid.GroupType.GROUPTYPE_FAMILY));
                    var familyGroupList       = groupMemberService.Queryable().Where(g => g.PersonId == person.Id &&
                                                                                     g.Group.GroupType.Guid == familyGroupType.Guid).Select(g => g.Group).ToList();

                    if (!familyGroupList.Any())
                    {
                        familyGroup                = new Group();
                        familyGroup.IsActive       = true;
                        familyGroup.IsSystem       = false;
                        familyGroup.IsSecurityRole = false;
                        familyGroup.Name           = "The " + txtLastName.Text + " Family";
                        familyGroup.GroupTypeId    = familyGroupType.Id;
                        groupService.Add(familyGroup, person.Id);
                        groupService.Save(familyGroup, person.Id);

                        var familyMember         = new GroupMember();
                        familyMember.IsSystem    = false;
                        familyMember.GroupId     = familyGroup.Id;
                        familyMember.PersonId    = person.Id;
                        familyMember.GroupRoleId = new GroupRoleService().Get(new Guid(Rock.SystemGuid.GroupRole.GROUPROLE_FAMILY_MEMBER_ADULT)).Id;
                        groupMemberService.Add(familyMember, person.Id);
                        groupMemberService.Save(familyMember, person.Id);
                    }
                    else
                    {
                        familyGroup = familyGroupList.FirstOrDefault();
                    }

                    var groupLocationList = groupLocationService.Queryable().Where(g => g.GroupLocationTypeValueId == familyGroupType.Id &&
                                                                                   g.GroupId == familyGroup.Id).ToList();

                    if (!groupLocationList.Any())
                    {
                        groupLocation            = new GroupLocation();
                        groupLocation.GroupId    = familyGroup.Id;
                        groupLocation.LocationId = homeAddress.Id;
                        groupLocation.IsMailing  = true;
                        groupLocation.IsLocation = true;
                        groupLocation.GroupLocationTypeValueId = homeLocationType.Id;
                        groupLocationService.Add(groupLocation, person.Id);
                        groupLocationService.Save(groupLocation, person.Id);
                    }
                    else
                    {
                        groupLocation = groupLocationList.FirstOrDefault();
                    }

                    groupLocation.LocationId = homeAddress.Id;
                    groupLocationService.Save(groupLocation, person.Id);

                    var homePhoneType   = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.PERSON_PHONE_TYPE_HOME);
                    string phoneNumeric = txtPhone.Text.AsNumeric();
                    if (!phoneService.Queryable().Where(n => n.PersonId == person.Id &&
                                                        n.NumberTypeValueId == homePhoneType.Id && n.Number == phoneNumeric).Any())
                    {
                        var homePhone                = new PhoneNumber();
                        homePhone.Number             = phoneNumeric;
                        homePhone.PersonId           = person.Id;
                        homePhone.IsSystem           = false;
                        homePhone.IsMessagingEnabled = false;
                        homePhone.IsUnlisted         = false;
                        homePhone.NumberTypeValueId  = homePhoneType.Id;
                        phoneService.Add(homePhone, person.Id);
                        phoneService.Save(homePhone, person.Id);
                    }
                });
            }

            var      amountList   = (Dictionary <FinancialAccount, Decimal>)Session["CachedAmounts"];
            var      profileId    = (int)Session["CachedProfileId"];
            Location giftLocation = new Location();

            var configValues = (Dictionary <string, object>)Session["CachedMergeFields"];

            configValues.Add("Date", DateTimeOffset.Now.ToString("MM/dd/yyyy hh:mm tt"));

            var receiptTemplate = GetAttributeValue("ReceiptMessage");

            lReceipt.Text = receiptTemplate.ResolveMergeFields(configValues);
            var    summaryTemplate = GetAttributeValue("SummaryMessage");
            string summaryMessage  = summaryTemplate.ResolveMergeFields(configValues);

            var creditProcessorId = GetAttributeValue("CreditCardProvider");
            var achProcessorId    = GetAttributeValue("Checking/ACHProvider");
            var gatewayService    = new FinancialGatewayService();
            FinancialGateway gateway;

            if (!string.IsNullOrEmpty(txtCreditCard.Text) && !string.IsNullOrWhiteSpace(creditProcessorId))
            {
                int creditId = Convert.ToInt32(creditProcessorId);
                gateway = new FinancialGatewayService().Get(creditId);
            }
            else if (!string.IsNullOrEmpty(txtAccountNumber.Text) && !string.IsNullOrWhiteSpace(achProcessorId))
            {
                int achId = Convert.ToInt32(achProcessorId);
                gateway = new FinancialGatewayService().Get(achId);
            }
            else
            {
                gateway = gatewayService.Queryable().FirstOrDefault();
            }

            // #TODO test card through gateway

            if (btnFrequency.SelectedIndex > -1 && btnFrequency.SelectedValueAsInt() != DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.TRANSACTION_FREQUENCY_TYPE_ONE_TIME).Id)
            {
                using (new UnitOfWorkScope())
                {
                    RockTransactionScope.WrapTransaction(() =>
                    {
                        var scheduledTransactionDetailService = new FinancialScheduledTransactionDetailService();
                        var scheduledTransactionService       = new FinancialScheduledTransactionService();
                        FinancialScheduledTransaction scheduledTransaction;
                        var detailList = amountList.ToList();

                        if (profileId > 0)
                        {
                            scheduledTransaction = scheduledTransactionService.Get(profileId);
                        }
                        else
                        {
                            scheduledTransaction = new FinancialScheduledTransaction();
                            scheduledTransactionService.Add(scheduledTransaction, person.Id);
                        }

                        DateTime startDate = (DateTime)dtpStartDate.SelectedDate;
                        if (startDate != null)
                        {
                            scheduledTransaction.StartDate = startDate;
                        }

                        scheduledTransaction.TransactionFrequencyValueId = (int)btnFrequency.SelectedValueAsInt();
                        scheduledTransaction.AuthorizedPersonId          = person.Id;
                        scheduledTransaction.IsActive = true;

                        if (!string.IsNullOrEmpty(txtCreditCard.Text))
                        {
                            scheduledTransaction.CardReminderDate = mypExpiration.SelectedDate;
                        }

                        if (chkLimitGifts.Checked && !string.IsNullOrWhiteSpace(txtLimitNumber.Text))
                        {
                            scheduledTransaction.NumberOfPayments = Convert.ToInt32(txtLimitNumber.Text);
                        }

                        foreach (var detail in amountList.ToList())
                        {
                            var scheduledTransactionDetail       = new FinancialScheduledTransactionDetail();
                            scheduledTransactionDetail.AccountId = detail.Key.Id;
                            scheduledTransactionDetail.Amount    = detail.Value;
                            scheduledTransactionDetail.ScheduledTransactionId = scheduledTransaction.Id;
                            scheduledTransactionDetailService.Add(scheduledTransactionDetail, person.Id);
                            scheduledTransactionDetailService.Save(scheduledTransactionDetail, person.Id);
                        }

                        // implement gateway charge()

                        scheduledTransactionService.Save(scheduledTransaction, person.Id);
                    });
                }
            }
            else
            {
                using (new UnitOfWorkScope())
                {
                    RockTransactionScope.WrapTransaction(() =>
                    {
                        var transactionService = new FinancialTransactionService();
                        var tdService          = new FinancialTransactionDetailService();
                        var transaction        = new FinancialTransaction();
                        var detailList         = amountList.ToList();

                        transaction.Summary = summaryMessage;
                        transaction.Amount  = detailList.Sum(d => d.Value);
                        transaction.TransactionTypeValueId = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION).Id;
                        transaction.TransactionDateTime    = DateTimeOffset.Now.DateTime;
                        transaction.AuthorizedPersonId     = person.Id;
                        transactionService.Add(transaction, person.Id);

                        foreach (var detail in detailList)
                        {
                            var td           = new FinancialTransactionDetail();
                            td.TransactionId = transaction.Id;
                            td.AccountId     = detail.Key.Id;
                            td.Amount        = detail.Value;
                            td.TransactionId = transaction.Id;
                            tdService.Add(td, person.Id);
                            tdService.Save(td, person.Id);
                        }

                        // #TODO implement gateway.charge()

                        transactionService.Save(transaction, person.Id);
                    });
                }
            }

            Session["CachedMergeFields"] = configValues;
            pnlConfirm.Visible           = false;
            pnlComplete.Visible          = true;
            pnlContribution.Update();
        }
Пример #6
0
        /// <summary>Process all transactions (payments) from Service Reef.</summary>
        /// <param name="message">The message that is returned depending on the result.</param>
        /// <param name="state">The state of the process.</param>
        /// <returns><see cref="WorkerResultStatus"/></returns>
        public void Execute(IJobExecutionContext context)
        {
            RockContext                 dbContext                   = new RockContext();
            FinancialBatchService       financialBatchService       = new FinancialBatchService(dbContext);
            PersonService               personService               = new PersonService(dbContext);
            PersonAliasService          personAliasService          = new PersonAliasService(dbContext);
            FinancialAccountService     financialAccountService     = new FinancialAccountService(dbContext);
            FinancialAccountService     accountService              = new FinancialAccountService(dbContext);
            FinancialTransactionService financialTransactionService = new FinancialTransactionService(dbContext);
            FinancialGatewayService     financialGatewayService     = new FinancialGatewayService(dbContext);
            DefinedValueService         definedValueService         = new DefinedValueService(dbContext);
            DefinedTypeService          definedTypeService          = new DefinedTypeService(dbContext);
            TransactionService          transactionService          = new TransactionService(new PayPalReporting.Data.PayPalReportingContext());

            // Get the datamap for loading attributes
            JobDataMap dataMap = context.JobDetail.JobDataMap;

            String warnings = string.Empty;

            FinancialBatch batch       = null;
            Double         totalAmount = 0;
            var            total       = 1;
            var            processed   = 0;

            try
            {
                DateRange dateRange = Rock.Web.UI.Controls.SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(dataMap.GetString("DateRange") ?? "-1||");

                String            SRApiKey          = Encryption.DecryptString(dataMap.GetString("ServiceReefAPIKey"));
                String            SRApiSecret       = Encryption.DecryptString(dataMap.GetString("ServiceReefAPISecret"));
                String            SRApiUrl          = dataMap.GetString("ServiceReefAPIURL");
                DefinedValueCache transactionSource = DefinedValueCache.Read(dataMap.GetString("TransactionSource").AsGuid(), dbContext);
                DefinedValueCache connectionStatus  = DefinedValueCache.Read(dataMap.GetString("ConnectionStatus").AsGuid(), dbContext);
                DefinedValueCache contribution      = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION);

                // Setup some lookups
                DefinedTypeCache        creditCards = DefinedTypeCache.Read(Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE.AsGuid(), dbContext);
                DefinedTypeCache        tenderType  = DefinedTypeCache.Get(Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE.AsGuid(), dbContext);
                FinancialAccount        specialFund = accountService.Get(dataMap.GetString("Account").AsGuid());
                FinancialGateway        gateway     = financialGatewayService.Get(dataMap.GetString("FinancialGateway").AsGuid());
                List <FinancialAccount> trips       = financialAccountService.Queryable().Where(fa => fa.ParentAccountId == specialFund.Id).OrderBy(fa => fa.Order).ToList();

                // Get the trips
                DefinedValueCache serviceReefAccountType = DefinedValueCache.Get(dataMap.Get("ServiceReefAccountType").ToString().AsGuid());

                // Setup the ServiceReef API Client
                var client = new RestClient(SRApiUrl);
                client.Authenticator = new HMACAuthenticator(SRApiKey, SRApiSecret);

                // Get all payments from ServiceReef
                var request = new RestRequest("v1/payments", Method.GET);
                request.AddParameter("pageSize", 100);
                if (dateRange.Start.HasValue)
                {
                    request.AddParameter("startDate", dateRange.Start.Value.ToString("o"));
                }
                if (dateRange.End.HasValue)
                {
                    request.AddParameter("endDate", dateRange.End.Value.ToString("o"));
                }
                request.AddParameter("page", 1);

                while (total > processed)
                {
                    var response = client.Execute <Contracts.Payments>(request);
                    if (response.StatusCode != System.Net.HttpStatusCode.OK)
                    {
                        throw new Exception("ServiceReef API Response: " + response.StatusDescription + " Content Length: " + response.ContentLength);
                    }
                    if (response.Data != null && response.Data.PageInfo != null)
                    {
                        total = response.Data.PageInfo.TotalRecords;
                        foreach (Contracts.Payments.Result result in response.Data.Results)
                        {
                            // Process the transaction
                            if (result.PaymentProcessorTransactionId != null)
                            {
                                if (result.FirstName == null || result.LastName == null)
                                {
                                    warnings += "Missing Firstname/Lastname for ServiceReef transaction Id: " + result.TransactionId + Environment.NewLine;
                                    processed++;
                                    continue;
                                }
                                FinancialAccount trip = null;
                                // Make sure we have a sub-account to go with this transaction
                                if (result.EventId > 0)
                                {
                                    trip = trips.Where(t => t.GlCode == result.EventCode && t.Url == result.EventUrl).FirstOrDefault();
                                }
                                if (trip == null)
                                {
                                    if (result.EventCode == null)
                                    {
                                        warnings += "Event Code is missing on the Service Reef Trip for ServiceReef transaction Id: " + result.TransactionId + Environment.NewLine;
                                        processed++;
                                        continue;
                                    }

                                    // Create the trip subaccount
                                    FinancialAccount tripFA = new FinancialAccount();
                                    tripFA.Name = result.EventName;
                                    // Name is limited to 50
                                    if (tripFA.Name.Length > 50)
                                    {
                                        tripFA.Name = tripFA.Name.Substring(0, 50);
                                    }
                                    tripFA.Description = "Service Reef Event.  Name: " + result.EventName + " ID: " + result.EventId;
                                    tripFA.GlCode      = result.EventCode;
                                    tripFA.Url         = result.EventUrl;
                                    tripFA.PublicName  = result.EventName;
                                    // Public Name is limited to 50
                                    if (tripFA.PublicName.Length > 50)
                                    {
                                        tripFA.PublicName = tripFA.PublicName.Substring(0, 50);
                                    }
                                    tripFA.IsTaxDeductible    = true;
                                    tripFA.IsPublic           = false;
                                    tripFA.ParentAccountId    = specialFund.Id;
                                    tripFA.Order              = specialFund.Order + 1;
                                    tripFA.AccountTypeValueId = serviceReefAccountType.Id;
                                    // Figure out what order it should be;
                                    foreach (FinancialAccount tmpTrip in trips)
                                    {
                                        if (tmpTrip.Name.CompareTo(tripFA.Name) < 0)
                                        {
                                            tripFA.Order++;
                                        }
                                    }

                                    financialAccountService.Add(tripFA);

                                    // Now save the trip
                                    dbContext.SaveChanges();
                                    // Increment all the rest of the Orders
                                    financialAccountService.Queryable().Where(fa => fa.Order >= tripFA.Order && fa.Id != tripFA.Id).ToList().ForEach(c => c.Order++);
                                    dbContext.SaveChanges();
                                    trips = financialAccountService.Queryable().Where(fa => fa.ParentAccountId == specialFund.Id).OrderBy(fa => fa.Order).ToList();
                                    trip  = tripFA;
                                }

                                FinancialTransaction tran = financialTransactionService.Queryable().Where(tx => tx.TransactionCode == result.PaymentProcessorTransactionId).FirstOrDefault();

                                // We haven't processed this before so get busy!
                                if (tran == null)
                                {
                                    tran = new FinancialTransaction();
                                    tran.FinancialPaymentDetail = new FinancialPaymentDetail();
                                    if (result.Type == "CreditCard")
                                    {
                                        tran.FinancialPaymentDetail.CurrencyTypeValueId = tenderType.DefinedValues.Where(t => t.Value == "Credit Card").FirstOrDefault().Id;
                                    }
                                    else
                                    {
                                        tran.TransactionTypeValueId = tenderType.DefinedValues.Where(t => t.Value == "Credit Card").FirstOrDefault().Id;
                                    }

                                    Person person = null;
                                    // Find the person this transaction belongs to
                                    // 1. First start by determining whether this was a person
                                    //    paying their application fee or contributing to themselves
                                    //    because then we can just use their member info
                                    if (result.UserId > 0 &&
                                        result.DonatedToUserId == result.UserId &&
                                        result.DonatedToFirstName == result.FirstName &&
                                        result.DonatedToLastName == result.LastName)
                                    {
                                        var memberRequest = new RestRequest("v1/members/{userId}", Method.GET);
                                        memberRequest.AddUrlSegment("userId", result.UserId.ToString());
                                        var memberResult = client.Execute <Contracts.Member>(memberRequest);
                                        if (memberResult.Data != null && memberResult.Data.ArenaId > 0)
                                        {
                                            try
                                            {
                                                Person personMatch = personAliasService.Queryable().Where(pa => pa.AliasPersonId == memberResult.Data.ArenaId).Select(pa => pa.Person).FirstOrDefault();
                                                if (personMatch == null)
                                                {
                                                    throw new Exception("Person not found: " + memberResult.Data.ArenaId);
                                                }
                                                person = personMatch;
                                            } catch (Exception e)
                                            {
                                                warnings += "Loading the person failed transaction id " + result.TransactionId + " for " + result.FirstName + " " + result.LastName + " with the following error: " + e.Message + Environment.NewLine;
                                                processed++;
                                                continue;
                                            }
                                        }
                                    }
                                    // 2. If we didn't get a person match via their Alias Id
                                    //    then just use the standard person match logic
                                    if (person == null)
                                    {
                                        String street1    = null;
                                        String postalCode = null;
                                        if (result.Address != null)
                                        {
                                            street1    = result.Address.Address1;
                                            postalCode = result.Address.Zip;
                                        }
                                        List <Person> matches = personService.GetByMatch(result.FirstName.Trim(), result.LastName.Trim(), null, result.Email, null, street1, postalCode).ToList();

                                        if (matches.Count > 1)
                                        {
                                            // Find the oldest member record in the list
                                            person = matches.Where(p => p.ConnectionStatusValue.Value == "Member").OrderBy(p => p.Id).FirstOrDefault();
                                            if (person == null)
                                            {
                                                // Find the oldest attendee record in the list
                                                person = matches.Where(p => p.ConnectionStatusValue.Value == "Attendee").OrderBy(p => p.Id).FirstOrDefault();
                                                if (person == null)
                                                {
                                                    person = matches.OrderBy(p => p.Id).First();
                                                }
                                            }
                                        }
                                        else if (matches.Count == 1)
                                        {
                                            person = matches.First();
                                        }
                                        else
                                        {
                                            // Create the person
                                            person           = new Person();
                                            person.FirstName = result.FirstName.Trim();
                                            person.LastName  = result.LastName.Trim();
                                            if (result.Email.IsValidEmail())
                                            {
                                                person.Email = result.Email.Trim();
                                            }
                                            person.RecordTypeValueId       = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.PERSON_RECORD_TYPE_PERSON.AsGuid()).Id;
                                            person.ConnectionStatusValueId = connectionStatus.Id;
                                            person.RecordStatusValueId     = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_ACTIVE.AsGuid()).Id;
                                            Group         family   = PersonService.SaveNewPerson(person, dbContext);
                                            GroupLocation location = new GroupLocation();
                                            location.GroupLocationTypeValueId = DefinedValueCache.Read(Rock.SystemGuid.DefinedValue.GROUP_LOCATION_TYPE_HOME).Id;
                                            location.Location = new Location()
                                            {
                                                Street1    = result.Address.Address1,
                                                Street2    = result.Address.Address2,
                                                City       = result.Address.City,
                                                State      = result.Address.State,
                                                PostalCode = result.Address.Zip,
                                                Country    = result.Address.Country
                                            };
                                            family.CampusId = CampusCache.All().FirstOrDefault().Id;
                                            family.GroupLocations.Add(location);
                                            dbContext.SaveChanges();
                                        }
                                    }

                                    // Get details about the transaction from our PayPal report table
                                    Transaction tx = transactionService.Get(result.PaymentProcessorTransactionId);
                                    if (tx != null)
                                    {
                                        if (tx.TenderType.Contains("ACH"))
                                        {
                                            result.Type   = "ACH";
                                            result.Method = null;
                                        }
                                        else
                                        {
                                            result.Type   = "Credit Card";
                                            result.Method = tx.TenderType;
                                        }
                                    }
                                    else
                                    {
                                        // Defaults
                                        result.Type   = "Credit Card";
                                        result.Method = "Visa";

                                        warnings += "Unable to find transaction in _org_secc_PaypalReporting_Transaction table: " + result.TransactionId + Environment.NewLine;
                                    }

                                    // If we don't have a batch, create one
                                    if (batch == null)
                                    {
                                        batch = new FinancialBatch();
                                        batch.BatchStartDateTime = result.Date;
                                        batch.BatchEndDateTime   = DateTime.Now;
                                        batch.Name   = "Service Reef Payments";
                                        batch.Status = BatchStatus.Open;
                                        financialBatchService.Add(batch);
                                        dbContext.SaveChanges();
                                    }

                                    // Complete the FinancialTransaction
                                    tran.AuthorizedPersonAliasId = person.PrimaryAliasId;
                                    tran.BatchId             = batch.Id;
                                    tran.Summary             = "F" + specialFund.Id + ":$" + result.Amount.ToString();
                                    tran.TransactionDateTime = result.Date;
                                    tran.FinancialGatewayId  = gateway.Id;

                                    FinancialTransactionDetail financialTransactionDetail = new FinancialTransactionDetail();
                                    financialTransactionDetail.AccountId = trip.Id;
                                    financialTransactionDetail.Amount    = result.Amount.ToString().AsDecimal();
                                    tran.TransactionDetails.Add(financialTransactionDetail);
                                    tran.TransactionTypeValueId = contribution.Id;

                                    tran.FinancialPaymentDetail = new FinancialPaymentDetail();
                                    tran.FinancialPaymentDetail.CurrencyTypeValueId = tenderType.DefinedValues.Where(type => type.Value.ToLower() == result.Type.ToLower()).FirstOrDefault().Id;
                                    if (result.Method != null)
                                    {
                                        tran.FinancialPaymentDetail.CreditCardTypeValueId = creditCards.DefinedValues.Where(card => card.Value.ToLower() == result.Method.ToLower()).FirstOrDefault().Id;
                                    }
                                    tran.TransactionCode   = result.PaymentProcessorTransactionId;
                                    tran.SourceTypeValueId = transactionSource.Id;

                                    financialTransactionService.Add(tran);
                                    dbContext.SaveChanges();

                                    totalAmount += result.Amount;
                                }
                            }
                            processed++;
                        }
                    }
                    else
                    {
                        total = 0;
                    }
                    // Update the page number for the next request
                    var pageParam = request.Parameters.Where(p => p.Name == "page").FirstOrDefault();
                    pageParam.Value = (int)pageParam.Value + 1;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("ServiceReef Job Failed", ex);
            } finally
            {
                if (batch != null && totalAmount > 0)
                {
                    batch.ControlAmount = (Decimal)totalAmount;
                }
                dbContext.SaveChanges();
            }
            if (warnings.Length > 0)
            {
                throw new Exception(warnings);
            }
            context.Result = "Successfully imported " + processed + " transactions.";
        }
Пример #7
0
        /// <summary>
        /// Handles the Click event of the lbSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        protected void lbSave_Click(object sender, EventArgs e)
        {
            var rockContext = new RockContext();

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

            FinancialTransaction txn = null;

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

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