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