protected void Page_Load (object sender, EventArgs e) { _transaction = GetTransaction(); if (!_authority.HasPermission(Permission.CanSeeEconomyTransactions, _transaction.OrganizationId, -1, Authorization.Flag.ExactOrganization)) throw new UnauthorizedAccessException("Access Denied"); if (!Page.IsPostBack) { // Populate all data this.DatePicker.DateInput.Culture = new CultureInfo("sv-SE"); this.DatePicker.SelectedDate = _transaction.DateTime; this.TextDescription.Text = _transaction.Description; this.TextDescription.Style.Add(HtmlTextWriterStyle.Width, "100%"); PopulateGrid(); PopulateEvents(); IHasIdentity dependency = _transaction.Dependency; } Documents documents = _transaction.Documents; Page.Title = "Auditing Transaction #" + _transaction.Identity.ToString(); }
public static void MatchTransactionOpenPayout(int transactionId, int payoutId) { if (transactionId == 0 || payoutId == 0) { return; } AuthenticationData authData = GetAuthenticationDataAndCulture(); if ( !authData.Authority.HasAccess(new Access(authData.CurrentOrganization, AccessAspect.BookkeepingDetails))) { throw new UnauthorizedAccessException(); } FinancialTransaction transaction = FinancialTransaction.FromIdentity(transactionId); Payout payout = Payout.FromIdentity(payoutId); if (transaction.OrganizationId != authData.CurrentOrganization.Identity || payout.OrganizationId != authData.CurrentOrganization.Identity) { throw new UnauthorizedAccessException(); } Int64 transactionCents = transaction.Rows.AmountCentsTotal; Int64 payoutCents = payout.AmountCents; FinancialAccount forexSpillAccount = authData.CurrentOrganization.FinancialAccounts.IncomeCurrencyFluctuations; if (forexSpillAccount == null && payoutCents != -transactionCents) // the tx-negative is because it's a payout { throw new InvalidOperationException("Need forex gain/loss accounts for this operation"); // TODO: Autocreate? } if ((-transactionCents) < payoutCents) // the tx-negative is because it's a payout { // This is a forex loss, not a gain which is the default forexSpillAccount = authData.CurrentOrganization.FinancialAccounts.CostsCurrencyFluctuations; } if (-transactionCents != payoutCents) { // Forex adjust transaction.AddRow(forexSpillAccount, -(payoutCents + transactionCents), // plus because transactionCents is negative authData.CurrentUser); // Adds the forex adjustment so we can bind payout to tx and close } // The amounts should match now if (transaction.Rows.AmountCentsTotal != -payout.AmountCents) { throw new InvalidOperationException(); } payout.BindToTransactionAndClose(transaction, authData.CurrentUser); }
/// <summary> /// Charges the specified payment info. /// </summary> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Charge( PaymentInfo paymentInfo, out string errorMessage ) { errorMessage = string.Empty; var transaction = new FinancialTransaction(); transaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF"); return transaction; }
public static string GetTransactionDisplayIdentity(int transactionId) { GetAuthenticationDataAndCulture(); // Sets culture FinancialTransaction tx = FinancialTransaction.FromIdentity(transactionId); return(tx.OrganizationSequenceId.ToString("N0")); }
private static void SetDefaultTransaction(TransactionType transactionType) { SelectedTransaction = new FinancialTransaction { Type = (int)transactionType, IsExchangeModeActive = false, Currency = ServiceLocator.Current.GetInstance <SettingDataAccess>().DefaultCurrency }; }
private static void CheckIfRecurringWasRemoved(FinancialTransaction transaction) { if (!transaction.IsRecurring && transaction.ReccuringTransactionId.HasValue) { RecurringTransactionRepository.Delete(transaction.RecurringTransaction); transaction.ReccuringTransactionId = null; } }
public HttpResponseMessage PostScanned([FromBody] FinancialTransactionScannedCheck financialTransactionScannedCheck) { FinancialTransaction financialTransaction = financialTransactionScannedCheck.FinancialTransaction; financialTransaction.CheckMicrEncrypted = Encryption.EncryptString(financialTransactionScannedCheck.ScannedCheckMicr); financialTransaction.CheckMicrHash = Encryption.GetSHA1Hash(financialTransactionScannedCheck.ScannedCheckMicr); return(this.Post(financialTransaction)); }
private static async void PrehandleRemoveIfTransfer(FinancialTransaction transaction) { if (transaction.Type == (int)TransactionType.Transfer) { Func <double, double> amountFunc = x => - x; await HandleTransactionAmount(transaction, amountFunc, GetTargetAccountFunc()); } }
public static FinancialTransaction Translate(PCODonation inputTransaction) { var transaction = new FinancialTransaction(); transaction.Id = inputTransaction.id; if (inputTransaction.batchId.HasValue) { transaction.BatchId = inputTransaction.batchId.Value; } if (inputTransaction.payment_method == "check") { transaction.TransactionCode = inputTransaction.payment_check_number; } else if (inputTransaction.payment_method != "cash") { transaction.TransactionCode = inputTransaction.payment_last4; } transaction.TransactionDate = inputTransaction.received_at; transaction.AuthorizedPersonId = inputTransaction.personId; switch (inputTransaction.payment_method) { case "cash": transaction.CurrencyType = CurrencyType.Cash; break; case "check": transaction.CurrencyType = CurrencyType.Check; break; case "credit card": case "debit card": case "card": transaction.CurrencyType = CurrencyType.CreditCard; break; case "ach": transaction.CurrencyType = CurrencyType.ACH; break; case "non-cash": transaction.CurrencyType = CurrencyType.NonCash; break; default: transaction.CurrencyType = CurrencyType.Unknown; break; } transaction.CreatedDateTime = inputTransaction.created_at; transaction.ModifiedDateTime = inputTransaction.updated_at; return(transaction); }
public static FinancialTransaction Translate(DataRow row) { int? ID; string field; FinancialTransaction transaction = new FinancialTransaction(); // Identifiers transaction.Id = row.Field <int>("CONTRIBUTION_ID"); transaction.BatchId = row.Field <int>("BATCH_ID"); ID = row.Field <int?>("PERSON_ID"); if (ID != null) { transaction.AuthorizedPersonId = ID; // May not be found in either the csIND or csINDBin tables } // Other fields transaction.TransactionCode = row.Field <string>("CHECK_NO"); transaction.TransactionDate = row.Field <DateTime?>("BATCH_DT"); transaction.CreatedDateTime = row.Field <DateTime?>("CREATE_TS"); transaction.ModifiedDateTime = row.Field <DateTime?>("UPDATE_TS"); transaction.Summary = row.Field <string>("NOTE"); if (row.Field <string>("TAX_IND") == "1") { transaction.TransactionType = TransactionType.Contribution; } // Payment types can vary from Church to Church, so using the most popular ones here field = row.Field <string>("PAY_TYPE"); switch (field) { case "L": // Online transaction.TransactionSource = TransactionSource.Website; transaction.CurrencyType = CurrencyType.CreditCard; break; case "C": // Check transaction.TransactionSource = TransactionSource.OnsiteCollection; transaction.CurrencyType = CurrencyType.Check; break; case "S": // Cash transaction.TransactionSource = TransactionSource.OnsiteCollection; transaction.CurrencyType = CurrencyType.Cash; break; case "O": // Other transaction.TransactionSource = TransactionSource.OnsiteCollection; transaction.CurrencyType = CurrencyType.Unknown; // Slingshot won't import the Other value break; default: // Unknown transaction.TransactionSource = TransactionSource.OnsiteCollection; transaction.CurrencyType = CurrencyType.Unknown; break; } return(transaction); }
/// <summary> /// Credits the specified transaction. /// </summary> /// <param name="transaction">The transaction.</param> /// <param name="amount">The amount.</param> /// <param name="comment">The comment.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Credit(FinancialTransaction transaction, decimal amount, string comment, out string errorMessage) { errorMessage = string.Empty; var refundTransaction = new FinancialTransaction(); refundTransaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF"); return(refundTransaction); }
/// <summary> /// Charges the specified payment info. /// </summary> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Charge(PaymentInfo paymentInfo, out string errorMessage) { errorMessage = string.Empty; var transaction = new FinancialTransaction(); transaction.TransactionCode = "T" + RockDateTime.Now.ToString("yyyyMMddHHmmssFFF"); return(transaction); }
public override void Run() { HotBitcoinAddressUnspent utxoToReturn = HotBitcoinAddressUnspent.FromIdentity(UtxoIdentity); HotBitcoinAddress utxoAddress = utxoToReturn.Address; BitcoinSecret secretKey = utxoAddress.PrivateKey; // TODO: Verify that the utxoAddress is an EchoTest address, i.e. has second path component == BitcoinUtility.BitcoinEchoTestIndex string returnAddress = BitcoinUtility.GetInputAddressesForTransaction(BitcoinChain.Cash, utxoToReturn.TransactionHash)[0]; // assumes at least one input address -- not coinbase // Return the money BitcoinTransactionInputs inputs = utxoToReturn.AsInputs; Int64 satoshisToReturn = utxoToReturn.AmountSatoshis; Coin[] coins = inputs.Coins; ICoin[] iCoins = coins; ISecret[] privateKeys = utxoToReturn.AsInputs.PrivateKeys; TransactionBuilder txBuilder = new TransactionBuilder(); txBuilder = txBuilder.SendFees(new Satoshis(BitcoinUtility.EchoFeeSatoshis)); txBuilder = txBuilder.AddCoins(iCoins); txBuilder = txBuilder.AddKeys(privateKeys); if (returnAddress.StartsWith("1")) { txBuilder = txBuilder.Send(new BitcoinPubKeyAddress(returnAddress), new Satoshis(utxoToReturn.AmountSatoshis - BitcoinUtility.EchoFeeSatoshis)); } else if (returnAddress.StartsWith("3")) { txBuilder = txBuilder.Send(new BitcoinScriptAddress(returnAddress, Network.Main), new Satoshis(utxoToReturn.AmountSatoshis - BitcoinUtility.EchoFeeSatoshis)); } else { throw new ArgumentException("Unrecognized address format"); } Transaction tx = txBuilder.BuildTransaction(true, SigHash.ForkId | SigHash.All); BitcoinUtility.BroadcastTransaction(tx, BitcoinChain.Cash); utxoToReturn.Delete(); utxoAddress.UpdateTotal(); // Update the ledger string tx2Description = "Bitcoin echo test repayment"; FinancialTransaction ledgerTx2 = FinancialTransaction.Create(this.Organization, DateTime.UtcNow, tx2Description); ledgerTx2.AddRow(this.Organization.FinancialAccounts.DebtsOther, satoshisToReturn, this.Person); ledgerTx2.AddRow(this.Organization.FinancialAccounts.AssetsBitcoinHot, -satoshisToReturn, this.Person); ledgerTx2.BlockchainHash = tx.GetHash().ToString(); }
private string FormatSummary(FinancialTransaction txn) { var sb = new StringBuilder(); foreach (var transactionDetail in txn.TransactionDetails) { sb.AppendFormat("{0} (${1})<br>", transactionDetail.Account, transactionDetail.Amount); } return(sb.ToString()); }
public AccountState Event(ObligationSettledConcept occurred) { var trans = new FinancialTransaction(occurred.FinancialConcept, occurred.Amount); this.Obligations[occurred.ObligationNumber]?.PostTransaction(trans); return(new AccountState(this.AccountNumber, this.CurrentBalance, this.AccountStatus, this.Obligations, SimulatedFields, AuditLog.Add(new StateLog("ObligationSettledConcept", occurred.UniqueGuid(), occurred.OccurredOn())))); }
private string FormatSummary(FinancialTransaction txn) { var sb = new StringBuilder(); foreach (var transactionDetail in txn.TransactionDetails) { sb.AppendFormat("{0} ({2}{1})<br>", transactionDetail.Account, transactionDetail.Amount, GlobalAttributesCache.Value("CurrencySymbol")); } return(sb.ToString()); }
public void Adding_Debit_Transaction_Updates_Account_Balance() { var initialBalance = acc.GetBalance(); var trxToPost = new FinancialTransaction(defaultDebitAmount, "Testing Debit Transaction", DateTime.UtcNow, FinancialTransactionType.DEBIT); acc.PostTransaction(trxToPost); var updatedBalance = acc.GetBalance(); Assert.AreEqual(initialBalance - defaultDebitAmount, updatedBalance); }
/// <summary> /// Charges the specified payment info. /// </summary> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Charge(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage) { errorMessage = string.Empty; RequestMessage request = GetPaymentInfo(financialGateway, paymentInfo); if (request == null) { errorMessage = "Payment type not implemented"; return(null); } request.purchaseTotals = GetTotals(paymentInfo); request.billTo = GetBillTo(paymentInfo); request.item = GetItems(paymentInfo); if (!paymentInfo.CurrencyTypeValue.Guid.Equals(new Guid(Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD))) { request.ecDebitService = new ECDebitService(); request.ecDebitService.commerceIndicator = "internet"; request.ecDebitService.run = "true"; } else { request.ccAuthService = new CCAuthService(); request.ccAuthService.commerceIndicator = "internet"; request.ccAuthService.run = "true"; request.ccCaptureService = new CCCaptureService(); request.ccCaptureService.run = "true"; } ReplyMessage reply = SubmitTransaction(financialGateway, request); if (reply != null) { if (reply.reasonCode.Equals("100")) // SUCCESS { var transactionGuid = new Guid(reply.merchantReferenceCode); var transaction = new FinancialTransaction { Guid = transactionGuid }; transaction.TransactionCode = reply.requestID; return(transaction); } else { errorMessage = string.Format("Your order was not approved.{0}", ProcessError(reply)); } } else { errorMessage = "Invalid response from the financial gateway."; } return(null); }
/// <summary> /// Authorizes the specified payment info. /// </summary> /// <param name="financialGateway"></param> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Authorize(FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage) { errorMessage = string.Empty; Response ppResponse = null; var invoice = GetInvoice(paymentInfo); var tender = GetTender(paymentInfo); if (tender != null) { if (paymentInfo is ReferencePaymentInfo) { var reference = paymentInfo as ReferencePaymentInfo; var ppTransaction = new ReferenceTransaction("Authorization", reference.TransactionCode, GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId); ppResponse = ppTransaction.SubmitTransaction(); } else { var ppTransaction = new AuthorizationTransaction(GetUserInfo(financialGateway), GetConnection(financialGateway), invoice, tender, PayflowUtility.RequestId); ppResponse = ppTransaction.SubmitTransaction(); } } else { errorMessage = "Could not create tender from PaymentInfo"; } if (ppResponse != null) { TransactionResponse txnResponse = ppResponse.TransactionResponse; if (txnResponse != null) { if (txnResponse.Result == 0) // Success { var transaction = new FinancialTransaction(); transaction.TransactionCode = txnResponse.Pnref; return(transaction); } else { errorMessage = string.Format("[{0}] {1}", txnResponse.Result, txnResponse.RespMsg); } } else { errorMessage = "Invalid transaction response from the financial gateway"; } } else { errorMessage = "Invalid response from the financial gateway."; } return(null); }
/// <summary> /// Shows the detail. /// </summary> /// <param name="itemKey">The item key.</param> /// <param name="itemKeyValue">The item key value.</param> public void ShowDetail(string itemKey, int itemKeyValue) { if (!itemKey.Equals("transactionId") && !!itemKey.Equals("batchfk")) { return; } FinancialTransaction transaction = null; if (!itemKeyValue.Equals(0)) { transaction = new FinancialTransactionService(new RockContext()).Get(itemKeyValue); } else { transaction = new FinancialTransaction { Id = 0 }; } hfIdTransValue.Value = transaction.Id.ToString(); hfBatchId.Value = PageParameter("financialBatchId"); if (!readOnly) { lbEdit.Visible = true; if (transaction.Id > 0) { ShowSummary(transaction); } else { BindDropdowns(); ShowEdit(transaction); } gTransactionDetails.Actions.ShowAdd = true; gTransactionDetails.IsDeleteEnabled = true; pnlImageUpload.Visible = true; } else { lbEdit.Visible = false; ShowSummary(transaction); gTransactionDetails.Actions.ShowAdd = false; gTransactionDetails.IsDeleteEnabled = false; pnlImageUpload.Visible = false; } lbSave.Visible = !readOnly; LoadAccountDropDown(); BindTransactionDetailGrid(transaction); BindDefinedTypeDropdown(ddlTransactionImageType, new Guid(Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_IMAGE_TYPE), "Transaction Image Type"); LoadRelatedImages(transaction.Id); }
/// <summary> /// Handles the RowDataBound event of the gContributions control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="GridViewRowEventArgs"/> instance containing the event data.</param> protected void gContributions_RowDataBound(object sender, GridViewRowEventArgs e) { FinancialTransaction financialTransaction = e.Row.DataItem as FinancialTransaction; Literal lAddress = e.Row.FindControl("lAddress") as Literal; if (financialTransaction != null && lAddress != null && financialTransaction.AuthorizedPersonAliasId.HasValue) { var personAddress = financialTransaction.AuthorizedPersonAlias.Person.GetHomeLocation(); lAddress.Text = personAddress.GetFullStreetAddress(); } }
public void CloseBudget(Person closingPerson) { Int64 remainingFunds = -Budget.GetDeltaCents(CreatedDateTime, DateTime.Now); FinancialTransaction transaction = FinancialTransaction.Create(OrganizationId, DateTime.Now, "Closing conference #" + Identity); transaction.AddRow(Budget, remainingFunds, closingPerson); transaction.AddRow(Budget.Parent, -remainingFunds, closingPerson); }
public void FinancialTransactionShouldNotBeValid(string title, string description, double value) { var transactionDate = DateTime.Today; var financialTransaction = new FinancialTransaction(title, description, value, transactionDate); var financialValidator = new FinancialTransactionValidator(); var validationResult = financialValidator.Validate(financialTransaction); Assert.False(validationResult.IsValid); Assert.NotEmpty(validationResult.Errors); }
public static async Task AddTransactionAmount(FinancialTransaction transaction) { PrehandleAddIfTransfer(transaction); Func <double, double> amountFunc = x => transaction.Type == (int)TransactionType.Income ? x : -x; await HandleTransactionAmount(transaction, amountFunc, GetChargedAccountFunc()); }
protected void Page_Load(object sender, EventArgs e) { _transaction = GetTransaction(); if (!_authority.HasPermission(Permission.CanDoEconomyTransactions, _transaction.OrganizationId, -1, Authorization.Flag.ExactOrganization)) { throw new UnauthorizedAccessException("Access Denied"); } if (!Page.IsPostBack) { // Populate all data this.DatePicker.DateInput.Culture = new CultureInfo("sv-SE"); this.DatePicker.SelectedDate = _transaction.DateTime; this.TextDescription.Text = _transaction.Description; this.TextDescription.Style.Add(HtmlTextWriterStyle.Width, "100%"); this.TextAmount.Style.Add(HtmlTextWriterStyle.Width, "80px"); this.DropAccounts.Style.Add(HtmlTextWriterStyle.Width, "200px"); this.TextAmount.Text = (-_transaction.Rows.AmountTotal).ToString("N2", new CultureInfo("sv-SE")); PopulateAccounts(_transaction.OrganizationId); PopulateGrid(); IHasIdentity dependency = _transaction.Dependency; if (dependency != null) { this.PanelModifiableTransaction.Visible = false; this.PanelUnmodifiableTransaction.Visible = true; if (dependency is ExpenseClaim) { this.LabelDependency.Text = "Expense Claim #" + dependency.Identity.ToString(); this.PanelDependencyDocuments.Visible = true; this.DocumentsDependency.Documents = Documents.ForObject(dependency); } else if (dependency is Payout) { this.PanelDependencyDocuments.Visible = false; this.PanelPayoutDetails.Visible = true; this.LabelDependency.Text = "Payout #" + dependency.Identity.ToString(); this.LabelPayoutIdentity.Text = dependency.Identity.ToString(); this.LabelPayoutReference.Text = ((Payout)dependency).Reference; } } } this.DocumentList.Documents = _transaction.Documents; Page.Title = "Editing Transaction #" + _transaction.Identity.ToString(); }
public void SettledDateKeyGetsSetCorrectly() { var testList = TestDataHelper.GetAnalyticsSourceDateTestData(); foreach (var keyValue in testList) { FinancialTransaction financialTransaction = new FinancialTransaction(); financialTransaction.SettledDate = keyValue.Value; Assert.AreEqual(keyValue.Key, financialTransaction.SettledDateKey); } }
public IActionResult OnGet() { // Create a new instance of Financial transaction and set its FromUsername value from context. FinancialTransaction = new FinancialTransaction(); FinancialTransaction.FromUsername = _httpContextAccessor.HttpContext.User.FindFirstValue(ClaimTypes.Name); if (FinancialTransaction.FromUsername == null) { return(Forbid()); } return(Page()); }
/// <summary>Deletes a transaction from the database.</summary> /// <param name="transaction">Transaction to be deleted</param> /// <param name="account">Account the transaction will be deleted from</param> /// <returns>Returns true if successful</returns> public static async Task <bool> DeleteFinancialTransaction(FinancialTransaction transaction, Account account) { bool success = false; if (await DatabaseInteraction.DeleteFinancialTransaction(transaction, account)) { AllTransactions.Remove(transaction); success = true; } return(success); }
/// <summary>Attempts to add a Transaction to the database.</summary> /// <returns>Returns true if successfully added</returns> private async Task <bool> AddTransaction() { FinancialTransaction newTransaction = new FinancialTransaction(await AppState.GetNextFinancialTransactionIndex(), DateTimeHelper.Parse(TransactionDate.SelectedDate), TxtPayee.Text, CmbMajorCategory.SelectedValue.ToString(), CmbMinorCategory.SelectedValue.ToString(), TxtMemo.Text, DecimalHelper.Parse(TxtOutflow.Text), DecimalHelper.Parse(TxtInflow.Text), _selectedAccount.Name); _selectedAccount.AddTransaction(newTransaction); AppState.AllTransactions.Add(newTransaction); return(await AppState.AddFinancialTransaction(newTransaction, _selectedAccount)); }
private double HandleTransferAmount(FinancialTransaction transaction, double balance) { if (selectedAccount == transaction.ChargedAccount) { balance -= transaction.Amount; } else { balance += transaction.Amount; } return(balance); }
/// <summary> /// Sets the heading information. /// </summary> /// <param name="txn">The TXN.</param> private void SetHeadingInfo(FinancialTransaction txn) { if (txn.TransactionTypeValue != null) { hlType.Visible = true; hlType.Text = txn.TransactionTypeValue.Value; } else { hlType.Visible = false; } }
public static void PrepareEdit(FinancialTransaction transaction) { AddTransactionView.IsEdit = true; AddTransactionView.IsTransfer = transaction.Type == (int)TransactionType.Transfer; if (transaction.ReccuringTransactionId.HasValue && transaction.RecurringTransaction != null) { AddTransactionView.IsEndless = transaction.RecurringTransaction.IsEndless; AddTransactionView.Recurrence = transaction.RecurringTransaction.Recurrence; } TransactionRepository.Selected = transaction; }
protected void Page_Load (object sender, EventArgs e) { _transaction = GetTransaction(); if (!_authority.HasPermission(Permission.CanDoEconomyTransactions, _transaction.OrganizationId, -1, Authorization.Flag.ExactOrganization)) throw new UnauthorizedAccessException("Access Denied"); if (!Page.IsPostBack) { // Populate all data this.DatePicker.DateInput.Culture = new CultureInfo("sv-SE"); this.DatePicker.SelectedDate = _transaction.DateTime; this.TextDescription.Text = _transaction.Description; this.TextDescription.Style.Add(HtmlTextWriterStyle.Width, "100%"); this.TextAmount.Style.Add(HtmlTextWriterStyle.Width, "80px"); this.DropAccounts.Style.Add(HtmlTextWriterStyle.Width, "200px"); this.TextAmount.Text = (-_transaction.Rows.AmountTotal).ToString("N2", new CultureInfo("sv-SE")); PopulateAccounts(_transaction.OrganizationId); PopulateGrid(); IHasIdentity dependency = _transaction.Dependency; if (dependency != null) { this.PanelModifiableTransaction.Visible = false; this.PanelUnmodifiableTransaction.Visible = true; if (dependency is ExpenseClaim) { this.LabelDependency.Text = "Expense Claim #" + dependency.Identity.ToString(); this.PanelDependencyDocuments.Visible = true; this.DocumentsDependency.Documents = Documents.ForObject(dependency); } else if (dependency is Payout) { this.PanelDependencyDocuments.Visible = false; this.PanelPayoutDetails.Visible = true; this.LabelDependency.Text = "Payout #" + dependency.Identity.ToString(); this.LabelPayoutIdentity.Text = dependency.Identity.ToString(); this.LabelPayoutReference.Text = ((Payout) dependency).Reference; } } } this.DocumentList.Documents = _transaction.Documents; Page.Title = "Editing Transaction #" + _transaction.Identity.ToString(); }
/// <summary> /// Shows the detail. /// </summary> /// <param name="itemKey">The item key.</param> /// <param name="itemKeyValue">The item key value.</param> public void ShowDetail( string itemKey, int itemKeyValue ) { if ( !itemKey.Equals( "transactionId" ) && !!itemKey.Equals( "batchfk" ) ) { return; } FinancialTransaction transaction = null; if ( !itemKeyValue.Equals( 0 ) ) { transaction = new FinancialTransactionService( new RockContext() ).Get( itemKeyValue ); } else { transaction = new FinancialTransaction { Id = 0 }; } hfIdTransValue.Value = transaction.Id.ToString(); hfBatchId.Value = PageParameter( "financialBatchId" ); if ( !readOnly ) { lbEdit.Visible = true; if ( transaction.Id > 0 ) { ShowSummary( transaction ); } else { BindDropdowns(); ShowEdit( transaction ); } gTransactionDetails.Actions.ShowAdd = true; gTransactionDetails.IsDeleteEnabled = true; pnlImageUpload.Visible = true; } else { lbEdit.Visible = false; ShowSummary( transaction ); gTransactionDetails.Actions.ShowAdd = false; gTransactionDetails.IsDeleteEnabled = false; pnlImageUpload.Visible = false; } lbSave.Visible = !readOnly; LoadAccountDropDown(); BindTransactionDetailGrid( transaction ); BindDefinedTypeDropdown( ddlTransactionImageType, new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_IMAGE_TYPE ), "Transaction Image Type" ); LoadRelatedImages( transaction.Id ); }
/// <summary> /// Deletes the specified item. /// </summary> /// <param name="item">The item.</param> /// <returns></returns> public override bool Delete( FinancialTransaction item ) { if ( item.FinancialPaymentDetailId.HasValue ) { var paymentDetailsService = new FinancialPaymentDetailService( (Rock.Data.RockContext)this.Context ); var paymentDetail = paymentDetailsService.Get( item.FinancialPaymentDetailId.Value ); if ( paymentDetail != null ) { paymentDetailsService.Delete( paymentDetail ); } } return base.Delete( item ); }
/// <summary> /// Formats the type of the currency. /// </summary> /// <param name="txn">The TXN.</param> /// <returns></returns> protected string FormatCurrencyType( FinancialTransaction txn ) { string currencyType = string.Empty; string creditCardType = string.Empty; if ( txn.FinancialPaymentDetail != null && txn.FinancialPaymentDetail.CurrencyTypeValueId.HasValue ) { int currencyTypeId = txn.FinancialPaymentDetail.CurrencyTypeValueId.Value; var currencyTypeValue = DefinedValueCache.Read( currencyTypeId ); currencyType = currencyTypeValue != null ? currencyTypeValue.Value : string.Empty; if ( txn.FinancialPaymentDetail.CreditCardTypeValueId.HasValue ) { int creditCardTypeId = txn.FinancialPaymentDetail.CreditCardTypeValueId.Value; var creditCardTypeValue = DefinedValueCache.Read( creditCardTypeId ); creditCardType = creditCardTypeValue != null ? creditCardTypeValue.Value : string.Empty; return string.Format( "{0} - {1}", currencyType, creditCardType ); } } return currencyType; }
/// <summary> /// Creates the giving records for the given parameters. /// </summary> /// <param name="personGuid">The person unique identifier.</param> /// <param name="startingDate">The starting date.</param> /// <param name="endDate">The end date.</param> /// <param name="frequency">The frequency (onetime, weekly, monthly).</param> /// <param name="percentGive">The percent give.</param> /// <param name="growRatePercent">The grow rate percent.</param> /// <param name="growFrequencyWeeks">The grow frequency weeks.</param> /// <param name="specialGiftPercent">The special gift percent.</param> /// <param name="accountAmountDict">The account amount dictionary.</param> /// <param name="circularImageList">A circular linked list of imageUrls to use for the fake contribution checks.</param> /// <param name="rockContexe">A rock context.</param> private void CreateGiving( Guid personGuid, DateTime startingDate, DateTime endDate, Frequency frequency, int percentGive, int growRatePercent, int growFrequencyWeeks, int specialGiftPercent, Dictionary<int, decimal> accountAmountDict, LinkedList<string> circularImageList, RockContext rockContext ) { int weekNumber = 0; DateTime monthly = startingDate; var currencyTypeCheck = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK.AsGuid() ); var imageUrlNode = circularImageList.First ?? null; // foreach weekend or monthly between the starting and ending date... for ( DateTime date = startingDate; date <= endDate; date = frequency == Frequency.weekly ? date.AddDays( 7 ) : frequency == Frequency.monthly ? date.AddMonths( 1 ) : endDate.AddDays(1) ) { weekNumber = (int)(date - startingDate).TotalDays / 7; // increase by growRatePercent every growFrequencyWeeks if ( growFrequencyWeeks != 0 && growRatePercent != 0 && weekNumber !=0 && weekNumber % growFrequencyWeeks == 0 ) { var copy = accountAmountDict.ToDictionary( entry => entry.Key, entry => entry.Value ); foreach ( var item in accountAmountDict ) { decimal amount = Math.Round( ( item.Value * 0.01M ) + item.Value, 0 ); copy[item.Key] = amount; } accountAmountDict = copy; } // randomized skip/missed weeks int summerFactor = ( 7 <= date.Month && date.Month <= 9 ) ? summerPercentFactor : 0; if ( _random.Next( 0, 100 ) > percentGive - summerFactor ) { continue; // skip this week } FinancialBatch batch; if ( _contributionBatches.ContainsKey( date ) ) { batch = _contributionBatches[date]; } else { batch = new FinancialBatch { Id = 0, Guid = Guid.NewGuid(), BatchStartDateTime = date, BatchEndDateTime = date, Status = BatchStatus.Closed, ControlAmount = 0, Name = string.Format( "SampleData{0}", date.ToJavascriptMilliseconds() ), CreatedByPersonAliasId = CurrentPerson.PrimaryAliasId }; _contributionBatches.Add( date, batch ); } // Set up the new transaction FinancialTransaction financialTransaction = new FinancialTransaction { TransactionTypeValueId = _transactionTypeContributionId, Guid = Guid.NewGuid(), TransactionDateTime = date, AuthorizedPersonAliasId = _peopleAliasDictionary[personGuid] }; financialTransaction.FinancialPaymentDetail = new FinancialPaymentDetail(); financialTransaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeCheck.Id; financialTransaction.FinancialPaymentDetail.Guid = Guid.NewGuid(); // Add a transaction detail record for each account they're donating to foreach ( var item in accountAmountDict ) { FinancialTransactionDetail transactionDetail = new FinancialTransactionDetail { AccountId = item.Key, Amount = item.Value, Guid = Guid.NewGuid() }; financialTransaction.TransactionDetails.Add( transactionDetail ); } // Add the image to the transaction (if any) if ( imageUrlNode != null ) { FinancialTransactionImage transactionImage = new FinancialTransactionImage { BinaryFile = SaveImage( imageUrlNode.Value, _checkImageBinaryFileType, _checkImageBinaryFileTypeSettings, rockContext ), Guid = Guid.NewGuid(), }; financialTransaction.Images.Add( transactionImage ); imageUrlNode = imageUrlNode.Next ?? imageUrlNode.List.First; } // Update the batch with the new control amount batch.ControlAmount += financialTransaction.TotalAmount; batch.Transactions.Add( financialTransaction ); } }
/// <summary> /// Gets the bill to from a transaction. /// </summary> /// <param name="transaction">The transaction.</param> /// <returns></returns> private BillTo GetBillTo( FinancialTransaction transaction ) { BillTo billingInfo = new BillTo(); billingInfo.customerID = transaction.AuthorizedPersonAlias.Id.ToString(); billingInfo.firstName = transaction.AuthorizedPersonAlias.Person.FirstName.Left( 50 ); // up to 50 chars billingInfo.lastName = transaction.AuthorizedPersonAlias.Person.LastName.Left( 50 ); // up to 60 chars billingInfo.email = transaction.AuthorizedPersonAlias.Person.Email.Left( 255 ); // up to 255 chars billingInfo.ipAddress = Dns.GetHostEntry( Dns.GetHostName() ) .AddressList.FirstOrDefault( ip => ip.AddressFamily == AddressFamily.InterNetwork ).ToString(); return billingInfo; }
private string FormatSummary( FinancialTransaction txn ) { var sb = new StringBuilder(); foreach ( var transactionDetail in txn.TransactionDetails ) { sb.AppendFormat( "{0} (${1})<br>", transactionDetail.Account, transactionDetail.Amount ); } return sb.ToString(); }
/// <summary> /// Gets the reference number from the gateway for converting a transaction to a billing profile. /// </summary> /// <param name="transaction">The transaction.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override string GetReferenceNumber( FinancialTransaction transaction, out string errorMessage ) { errorMessage = string.Empty; var financialGateway = transaction.FinancialGateway; RequestMessage request = GetMerchantInfo( financialGateway ); request.billTo = GetBillTo( transaction ); request.recurringSubscriptionInfo = new RecurringSubscriptionInfo(); request.recurringSubscriptionInfo.frequency = "ON-DEMAND"; request.recurringSubscriptionInfo.amount = "0"; request.paySubscriptionCreateService = new PaySubscriptionCreateService(); request.paySubscriptionCreateService.run = "true"; request.paySubscriptionCreateService.paymentRequestID = transaction.TransactionCode; // Get the reference code ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage ); if ( reply != null && reply.reasonCode == GATEWAY_RESPONSE_SUCCESS ) { return reply.paySubscriptionCreateReply.subscriptionID; } else if ( string.IsNullOrEmpty( errorMessage ) ) { errorMessage = ProcessError( reply ); } return string.Empty; }
/// <summary> /// Processes the payments. /// </summary> /// <param name="gateway">The gateway.</param> /// <param name="batchNamePrefix">The batch name prefix.</param> /// <param name="payments">The payments.</param> /// <param name="batchUrlFormat">The batch URL format.</param> /// <returns></returns> public static string ProcessPayments( FinancialGateway gateway, string batchNamePrefix, List<Payment> payments, string batchUrlFormat = "" ) { int totalPayments = 0; int totalAlreadyDownloaded = 0; int totalNoScheduledTransaction = 0; int totalAdded = 0; var batches = new List<FinancialBatch>(); var batchSummary = new Dictionary<Guid, List<Payment>>(); var initialControlAmounts = new Dictionary<Guid, decimal>(); var allBatchChanges = new Dictionary<Guid, List<string>>(); var allTxnChanges = new Dictionary<Guid, List<string>>(); var txnPersonNames = new Dictionary<Guid, string>(); using ( var rockContext = new RockContext() ) { var accountService = new FinancialAccountService( rockContext ); var txnService = new FinancialTransactionService( rockContext ); var batchService = new FinancialBatchService( rockContext ); var scheduledTxnService = new FinancialScheduledTransactionService( rockContext ); var contributionTxnType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() ); var defaultAccount = accountService.Queryable() .Where( a => a.IsActive && !a.ParentAccountId.HasValue && ( !a.StartDate.HasValue || a.StartDate.Value <= RockDateTime.Now ) && ( !a.EndDate.HasValue || a.EndDate.Value >= RockDateTime.Now ) ) .OrderBy( a => a.Order ) .FirstOrDefault(); var batchTxnChanges = new Dictionary<Guid, List<string>>(); var batchBatchChanges = new Dictionary<Guid, List<string>>(); foreach ( var payment in payments.Where( p => p.Amount > 0.0M ) ) { totalPayments++; // Only consider transactions that have not already been added if ( txnService.GetByTransactionCode( payment.TransactionCode ) == null ) { var scheduledTransaction = scheduledTxnService.GetByScheduleId( payment.GatewayScheduleId ); if ( scheduledTransaction != null ) { scheduledTransaction.IsActive = payment.ScheduleActive; var txnChanges = new List<string>(); var transaction = new FinancialTransaction(); transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); transaction.Guid = Guid.NewGuid(); allTxnChanges.Add( transaction.Guid, txnChanges ); txnChanges.Add( "Created Transaction (Downloaded from Gateway)" ); transaction.TransactionCode = payment.TransactionCode; History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode ); transaction.TransactionDateTime = payment.TransactionDateTime; History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime ); transaction.ScheduledTransactionId = scheduledTransaction.Id; transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId; History.EvaluateChange( txnChanges, "Person", string.Empty, scheduledTransaction.AuthorizedPersonAlias.Person.FullName ); txnPersonNames.Add( transaction.Guid, scheduledTransaction.AuthorizedPersonAlias.Person.FullName ); transaction.FinancialGatewayId = gateway.Id; History.EvaluateChange( txnChanges, "Gateway", string.Empty, gateway.Name ); transaction.TransactionTypeValueId = contributionTxnType.Id; History.EvaluateChange( txnChanges, "Type", string.Empty, contributionTxnType.Value ); var currencyTypeValue = payment.CurrencyTypeValue; var creditCardTypevalue = payment.CreditCardTypeValue; if ( scheduledTransaction.FinancialPaymentDetail != null ) { if ( currencyTypeValue == null && scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.HasValue ) { currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.Value ); } if ( creditCardTypevalue == null && scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.HasValue ) { creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.Value ); } transaction.FinancialPaymentDetail.AccountNumberMasked = scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked; transaction.FinancialPaymentDetail.NameOnCardEncrypted = scheduledTransaction.FinancialPaymentDetail.NameOnCardEncrypted; transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted; transaction.FinancialPaymentDetail.ExpirationYearEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted; } if ( currencyTypeValue != null ) { transaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeValue.Id; History.EvaluateChange( txnChanges, "Currency Type", string.Empty, currencyTypeValue.Value ); } if ( creditCardTypevalue != null ) { transaction.FinancialPaymentDetail.CreditCardTypeValueId = creditCardTypevalue.Id; History.EvaluateChange( txnChanges, "Credit Card Type", string.Empty, creditCardTypevalue.Value ); } //transaction.SourceTypeValueId = DefinedValueCache.Read( sourceGuid ).Id; // Try to allocate the amount of the transaction based on the current scheduled transaction accounts decimal remainingAmount = payment.Amount; foreach ( var detail in scheduledTransaction.ScheduledTransactionDetails.Where( d => d.Amount != 0.0M ) ) { var transactionDetail = new FinancialTransactionDetail(); transactionDetail.AccountId = detail.AccountId; if ( detail.Amount <= remainingAmount ) { // If the configured amount for this account is less than or equal to the remaining // amount, allocate the configured amount transactionDetail.Amount = detail.Amount; remainingAmount -= detail.Amount; } else { // If the configured amount is greater than the remaining amount, only allocate // the remaining amount transaction.Summary = "Note: Downloaded transaction amount was less than the configured allocation amounts for the Scheduled Transaction."; detail.Amount = remainingAmount; detail.Summary = "Note: The downloaded amount was not enough to apply the configured amount to this account."; remainingAmount = 0.0M; } transaction.TransactionDetails.Add( transactionDetail ); History.EvaluateChange( txnChanges, detail.Account.Name, 0.0M.ToString( "C2" ), transactionDetail.Amount.ToString( "C2" ) ); History.EvaluateChange( txnChanges, "Summary", string.Empty, transactionDetail.Summary ); if ( remainingAmount <= 0.0M ) { // If there's no amount left, break out of details break; } } // If there's still amount left after allocating based on current config, add the remainder // to the account that was configured for the most amount if ( remainingAmount > 0.0M ) { transaction.Summary = "Note: Downloaded transaction amount was greater than the configured allocation amounts for the Scheduled Transaction."; var transactionDetail = transaction.TransactionDetails .OrderByDescending( d => d.Amount ) .First(); if ( transactionDetail == null && defaultAccount != null ) { transactionDetail = new FinancialTransactionDetail(); transactionDetail.AccountId = defaultAccount.Id; } if ( transactionDetail != null ) { transactionDetail.Amount += remainingAmount; transactionDetail.Summary = "Note: Extra amount was applied to this account."; } History.EvaluateChange( txnChanges, defaultAccount.Name, 0.0M.ToString( "C2" ), transactionDetail.Amount.ToString( "C2" ) ); History.EvaluateChange( txnChanges, "Summary", string.Empty, transactionDetail.Summary ); } // Get the batch var batch = batchService.Get( batchNamePrefix, currencyTypeValue, creditCardTypevalue, transaction.TransactionDateTime.Value, gateway.GetBatchTimeOffset(), batches ); var batchChanges = new List<string>(); if ( batch.Id != 0 ) { initialControlAmounts.AddOrIgnore( batch.Guid, batch.ControlAmount ); } batch.ControlAmount += transaction.TotalAmount; batch.Transactions.Add( transaction ); // Add summary if ( !batchSummary.ContainsKey( batch.Guid ) ) { batchSummary.Add( batch.Guid, new List<Payment>() ); } batchSummary[batch.Guid].Add( payment ); totalAdded++; } else { totalNoScheduledTransaction++; } } else { totalAlreadyDownloaded++; } } foreach ( var batch in batches ) { var batchChanges = new List<string>(); allBatchChanges.Add( batch.Guid, batchChanges ); if ( batch.Id == 0 ) { batchChanges.Add( "Generated the batch" ); History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name ); History.EvaluateChange( batchChanges, "Status", null, batch.Status ); History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime ); History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime ); } if ( initialControlAmounts.ContainsKey( batch.Guid ) ) { History.EvaluateChange( batchChanges, "Control Amount", initialControlAmounts[batch.Guid].ToString( "C2" ), batch.ControlAmount.ToString( "C2" ) ); } } rockContext.WrapTransaction( () => { rockContext.SaveChanges(); foreach ( var batch in batches ) { HistoryService.SaveChanges( rockContext, typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), batch.Id, allBatchChanges[batch.Guid] ); foreach ( var transaction in batch.Transactions ) { if ( allTxnChanges.ContainsKey( transaction.Guid ) ) { HistoryService.SaveChanges( rockContext, typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), batch.Id, allTxnChanges[transaction.Guid], txnPersonNames[transaction.Guid], typeof( FinancialTransaction ), transaction.Id ); } } } rockContext.SaveChanges(); } ); } StringBuilder sb = new StringBuilder(); sb.AppendFormat( "<li>{0} {1} downloaded.</li>", totalPayments.ToString( "N0" ), ( totalPayments == 1 ? "payment" : "payments" ) ); if ( totalAlreadyDownloaded > 0 ) { sb.AppendFormat( "<li>{0} {1} previously downloaded and {2} already been added.</li>", totalAlreadyDownloaded.ToString( "N0" ), ( totalAlreadyDownloaded == 1 ? "payment was" : "payments were" ), ( totalAlreadyDownloaded == 1 ? "has" : "have" ) ); } if ( totalNoScheduledTransaction > 0 ) { sb.AppendFormat( "<li>{0} {1} could not be matched to an existing scheduled payment profile.</li>", totalNoScheduledTransaction.ToString( "N0" ), ( totalNoScheduledTransaction == 1 ? "payment" : "payments" ) ); } sb.AppendFormat( "<li>{0} {1} successfully added.</li>", totalAdded.ToString( "N0" ), ( totalAdded == 1 ? "payment was" : "payments were" ) ); foreach ( var batchItem in batchSummary ) { int items = batchItem.Value.Count; if (items > 0) { var batch = batches .Where( b => b.Guid.Equals( batchItem.Key ) ) .FirstOrDefault(); string batchName = string.Format("'{0} ({1})'", batch.Name, batch.BatchStartDateTime.Value.ToString("d")); if ( !string.IsNullOrWhiteSpace( batchUrlFormat ) ) { batchName = string.Format( "<a href='{0}'>{1}</a>", string.Format( batchUrlFormat, batch.Id ), batchName ); } decimal sum = batchItem.Value.Select( p => p.Amount ).Sum(); string summaryformat = items == 1 ? "<li>{0} transaction of {1} was added to the {2} batch.</li>" : "<li>{0} transactions totaling {1} were added to the {2} batch</li>"; sb.AppendFormat( summaryformat, items.ToString( "N0" ), sum.ToString( "C2" ), batchName ); } } return sb.ToString(); }
/// <summary> /// Charges the specified payment info. /// </summary> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Charge( PaymentInfo paymentInfo, out string errorMessage ) { errorMessage = string.Empty; Response ppResponse = null; var invoice = GetInvoice( paymentInfo ); var tender = GetTender( paymentInfo ); if ( tender != null ) { if ( paymentInfo is ReferencePaymentInfo ) { var reference = paymentInfo as ReferencePaymentInfo; var ppTransaction = new ReferenceTransaction( "Sale", reference.TransactionCode, GetUserInfo(), GetConnection(), invoice, tender, PayflowUtility.RequestId ); ppResponse = ppTransaction.SubmitTransaction(); } else { var ppTransaction = new SaleTransaction( GetUserInfo(), GetConnection(), invoice, tender, PayflowUtility.RequestId ); ppResponse = ppTransaction.SubmitTransaction(); } } else { errorMessage = "Could not create tender from PaymentInfo"; } if ( ppResponse != null ) { TransactionResponse txnResponse = ppResponse.TransactionResponse; if ( txnResponse != null ) { if ( txnResponse.Result == 0 ) // Success { var transaction = new FinancialTransaction(); transaction.TransactionCode = txnResponse.Pnref; return transaction; } else { errorMessage = string.Format( "[{0}] {1}", txnResponse.Result, txnResponse.RespMsg ); } } else { errorMessage = "Invalid transaction response from the financial gateway"; } } else { errorMessage = "Invalid response from the financial gateway."; } return null; }
/// <summary> /// Gets an optional reference identifier needed to process future transaction from saved account. /// </summary> /// <param name="transaction">The transaction.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override string GetReferenceNumber( FinancialTransaction transaction, out string errorMessage ) { errorMessage = string.Empty; return string.Empty; }
/// <summary> /// Authorizes/tokenizes the specified payment info. /// </summary> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Authorize( FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage ) { errorMessage = string.Empty; RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo ); if ( request == null ) { errorMessage = "Payment type not implemented"; return null; } if ( request.recurringSubscriptionInfo == null ) { request.recurringSubscriptionInfo = new RecurringSubscriptionInfo(); } request.recurringSubscriptionInfo.frequency = "ON-DEMAND"; request.recurringSubscriptionInfo.amount = paymentInfo.Amount.ToString(); request.paySubscriptionCreateService = new PaySubscriptionCreateService(); request.paySubscriptionCreateService.run = "true"; request.purchaseTotals = GetTotals(); request.billTo = GetBillTo( paymentInfo ); request.item = GetItems( paymentInfo ); request.subscription = new Subscription(); if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) ) { request.subscription.paymentMethod = "check"; } if ( paymentInfo is ReferencePaymentInfo ) { request.paySubscriptionCreateService.paymentRequestID = ( (ReferencePaymentInfo)paymentInfo ).TransactionCode; } // Authorize the transaction ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage ); if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) ) { var transactionGuid = new Guid( reply.merchantReferenceCode ); var transaction = new FinancialTransaction { Guid = transactionGuid }; transaction.TransactionCode = reply.requestID; return transaction; } else if ( string.IsNullOrEmpty( errorMessage ) ) { errorMessage = string.Format( "Unable to authorize this transaction.{0}", ProcessError( reply ) ); } return null; }
/// <summary> /// Credits (Refunds) the specified transaction. /// </summary> /// <param name="origTransaction">The original transaction.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Credit( FinancialTransaction origTransaction, decimal amount, string comment, out string errorMessage ) { errorMessage = string.Empty; if ( origTransaction == null ) { errorMessage = "Original transaction cannot be null"; return null; } if ( string.IsNullOrWhiteSpace( origTransaction.TransactionCode ) ) { errorMessage = "The transaction must have a TransactionCode to process a refund/credit"; return null; } if ( origTransaction.FinancialGateway == null ) { errorMessage = "The transaction must have a FinancialGateway to process a refund/credit"; return null; } var financialGateway = origTransaction.FinancialGateway; var request = GetMerchantInfo( financialGateway ); request.ccCreditService = new CCCreditService { run = "true", captureRequestID = origTransaction.TransactionCode }; request.comments = comment; request.purchaseTotals = GetTotals(); request.purchaseTotals.grandTotalAmount = amount.ToString(); // Credit the transaction ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage ); if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) ) { var transactionGuid = new Guid( reply.merchantReferenceCode ); var transaction = new FinancialTransaction { Guid = transactionGuid, TransactionCode = reply.requestID, Summary = comment }; return transaction; } else if ( string.IsNullOrEmpty( errorMessage ) ) { errorMessage = string.Format( "Unable to credit this transaction.{0}", ProcessError( reply ) ); } return null; }
/// <summary> /// Shows the detail. /// </summary> /// <param name="transactionId">The transaction identifier.</param> public void ShowDetail( int transactionId, int? batchId ) { FinancialTransaction txn = null; bool editAllowed = true; var rockContext = new RockContext(); if ( !transactionId.Equals( 0 ) ) { txn = GetTransaction( transactionId, rockContext ); if ( txn != null ) { editAllowed = txn.IsAuthorized( Authorization.EDIT, CurrentPerson ); } } if ( txn == null ) { txn = new FinancialTransaction { Id = 0 }; txn.BatchId = batchId; } hfTransactionId.Value = txn.Id.ToString(); hfBatchId.Value = batchId.HasValue ? batchId.Value.ToString() : string.Empty; bool readOnly = false; nbEditModeMessage.Text = string.Empty; if ( !editAllowed || !IsUserAuthorized( Authorization.EDIT ) ) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( FinancialTransaction.FriendlyTypeName ); } if ( readOnly ) { lbEdit.Visible = false; ShowReadOnlyDetails( txn ); } else { lbEdit.Visible = true; if ( txn.Id > 0 ) { ShowReadOnlyDetails( txn ); } else { ShowEditDetails( txn, rockContext ); } } lbSave.Visible = !readOnly; }
/// <summary> /// Processes the payments. /// </summary> /// <param name="gateway">The gateway.</param> /// <param name="batchNamePrefix">The batch name prefix.</param> /// <param name="payments">The payments.</param> /// <param name="batchUrlFormat">The batch URL format.</param> /// <param name="receiptEmail">The receipt email.</param> /// <returns></returns> public static string ProcessPayments( FinancialGateway gateway, string batchNamePrefix, List<Payment> payments, string batchUrlFormat = "", Guid? receiptEmail = null ) { int totalPayments = 0; int totalAlreadyDownloaded = 0; int totalNoScheduledTransaction = 0; int totalAdded = 0; int totalReversals = 0; int totalStatusChanges = 0; var batches = new List<FinancialBatch>(); var batchSummary = new Dictionary<Guid, List<Decimal>>(); var initialControlAmounts = new Dictionary<Guid, decimal>(); var txnPersonNames = new Dictionary<Guid, string>(); var gatewayComponent = gateway.GetGatewayComponent(); var newTransactions = new List<FinancialTransaction>(); using ( var rockContext = new RockContext() ) { var accountService = new FinancialAccountService( rockContext ); var txnService = new FinancialTransactionService( rockContext ); var batchService = new FinancialBatchService( rockContext ); var scheduledTxnService = new FinancialScheduledTransactionService( rockContext ); var contributionTxnType = DefinedValueCache.Read( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION.AsGuid() ); var defaultAccount = accountService.Queryable() .Where( a => a.IsActive && !a.ParentAccountId.HasValue && ( !a.StartDate.HasValue || a.StartDate.Value <= RockDateTime.Now ) && ( !a.EndDate.HasValue || a.EndDate.Value >= RockDateTime.Now ) ) .OrderBy( a => a.Order ) .FirstOrDefault(); var batchTxnChanges = new Dictionary<Guid, List<string>>(); var batchBatchChanges = new Dictionary<Guid, List<string>>(); var scheduledTransactionIds = new List<int>(); foreach ( var payment in payments.Where( p => p.Amount > 0.0M ) ) { totalPayments++; var scheduledTransaction = scheduledTxnService.GetByScheduleId( payment.GatewayScheduleId ); if ( scheduledTransaction != null ) { // Find existing payments with same transaction code var txns = txnService .Queryable( "TransactionDetails" ) .Where( t => t.TransactionCode == payment.TransactionCode ) .ToList(); // Calculate whether a transaction needs to be added var txnAmount = CalculateTransactionAmount( payment, txns ); if ( txnAmount != 0.0M ) { scheduledTransactionIds.Add( scheduledTransaction.Id ); if ( payment.ScheduleActive.HasValue ) { scheduledTransaction.IsActive = payment.ScheduleActive.Value; } var transaction = new FinancialTransaction(); transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); transaction.Guid = Guid.NewGuid(); transaction.TransactionCode = payment.TransactionCode; transaction.TransactionDateTime = payment.TransactionDateTime; transaction.Status = payment.Status; transaction.StatusMessage = payment.StatusMessage; transaction.ScheduledTransactionId = scheduledTransaction.Id; transaction.AuthorizedPersonAliasId = scheduledTransaction.AuthorizedPersonAliasId; transaction.SourceTypeValueId = scheduledTransaction.SourceTypeValueId; txnPersonNames.Add( transaction.Guid, scheduledTransaction.AuthorizedPersonAlias.Person.FullName ); transaction.FinancialGatewayId = gateway.Id; transaction.TransactionTypeValueId = contributionTxnType.Id; if ( txnAmount < 0.0M ) { transaction.Summary = "Reversal for previous transaction that failed during processing." + Environment.NewLine; } var currencyTypeValue = payment.CurrencyTypeValue; var creditCardTypevalue = payment.CreditCardTypeValue; if ( scheduledTransaction.FinancialPaymentDetail != null ) { if ( currencyTypeValue == null && scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.HasValue ) { currencyTypeValue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CurrencyTypeValueId.Value ); } if ( creditCardTypevalue == null && scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.HasValue ) { creditCardTypevalue = DefinedValueCache.Read( scheduledTransaction.FinancialPaymentDetail.CreditCardTypeValueId.Value ); } transaction.FinancialPaymentDetail.AccountNumberMasked = scheduledTransaction.FinancialPaymentDetail.AccountNumberMasked; transaction.FinancialPaymentDetail.NameOnCardEncrypted = scheduledTransaction.FinancialPaymentDetail.NameOnCardEncrypted; transaction.FinancialPaymentDetail.ExpirationMonthEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationMonthEncrypted; transaction.FinancialPaymentDetail.ExpirationYearEncrypted = scheduledTransaction.FinancialPaymentDetail.ExpirationYearEncrypted; transaction.FinancialPaymentDetail.BillingLocationId = scheduledTransaction.FinancialPaymentDetail.BillingLocationId; } if ( currencyTypeValue != null ) { transaction.FinancialPaymentDetail.CurrencyTypeValueId = currencyTypeValue.Id; } if ( creditCardTypevalue != null ) { transaction.FinancialPaymentDetail.CreditCardTypeValueId = creditCardTypevalue.Id; } // Try to allocate the amount of the transaction based on the current scheduled transaction accounts decimal remainingAmount = Math.Abs( txnAmount ); foreach ( var detail in scheduledTransaction.ScheduledTransactionDetails.Where( d => d.Amount != 0.0M ) ) { var transactionDetail = new FinancialTransactionDetail(); transactionDetail.AccountId = detail.AccountId; if ( detail.Amount <= remainingAmount ) { // If the configured amount for this account is less than or equal to the remaining // amount, allocate the configured amount transactionDetail.Amount = detail.Amount; remainingAmount -= detail.Amount; } else { // If the configured amount is greater than the remaining amount, only allocate // the remaining amount transaction.Summary += "Note: Downloaded transaction amount was less than the configured allocation amounts for the Scheduled Transaction."; transactionDetail.Amount = remainingAmount; transactionDetail.Summary = "Note: The downloaded amount was not enough to apply the configured amount to this account."; remainingAmount = 0.0M; } transaction.TransactionDetails.Add( transactionDetail ); if ( remainingAmount <= 0.0M ) { // If there's no amount left, break out of details break; } } // If there's still amount left after allocating based on current config, add the remainder // to the account that was configured for the most amount if ( remainingAmount > 0.0M ) { transaction.Summary += "Note: Downloaded transaction amount was greater than the configured allocation amounts for the Scheduled Transaction."; var transactionDetail = transaction.TransactionDetails .OrderByDescending( d => d.Amount ) .FirstOrDefault(); if ( transactionDetail == null && defaultAccount != null ) { transactionDetail = new FinancialTransactionDetail(); transactionDetail.AccountId = defaultAccount.Id; transaction.TransactionDetails.Add( transactionDetail ); } if ( transactionDetail != null ) { transactionDetail.Amount += remainingAmount; transactionDetail.Summary = "Note: Extra amount was applied to this account."; } } // If the amount to apply was negative, update all details to be negative (absolute value was used when allocating to accounts) if ( txnAmount < 0.0M ) { foreach ( var txnDetail in transaction.TransactionDetails ) { txnDetail.Amount = 0 - txnDetail.Amount; } } // Get the batch var batch = batchService.Get( batchNamePrefix, currencyTypeValue, creditCardTypevalue, transaction.TransactionDateTime.Value, gateway.GetBatchTimeOffset(), batches ); var batchChanges = new List<string>(); if ( batch.Id != 0 ) { initialControlAmounts.AddOrIgnore( batch.Guid, batch.ControlAmount ); } batch.ControlAmount += transaction.TotalAmount; batch.Transactions.Add( transaction ); if ( txnAmount > 0.0M && receiptEmail.HasValue ) { newTransactions.Add( transaction ); } // Add summary if ( !batchSummary.ContainsKey( batch.Guid ) ) { batchSummary.Add( batch.Guid, new List<Decimal>() ); } batchSummary[batch.Guid].Add( txnAmount ); if ( txnAmount > 0.0M ) { totalAdded++; } else { totalReversals++; } } else { totalAlreadyDownloaded++; foreach ( var txn in txns.Where( t => t.Status != payment.Status || t.StatusMessage != payment.StatusMessage ) ) { txn.Status = payment.Status; txn.StatusMessage = payment.StatusMessage; totalStatusChanges++; } } } else { totalNoScheduledTransaction++; } } rockContext.SaveChanges(); // Queue a transaction to update the status of all affected scheduled transactions var updatePaymentStatusTxn = new Rock.Transactions.UpdatePaymentStatusTransaction( gateway.Id, scheduledTransactionIds ); Rock.Transactions.RockQueue.TransactionQueue.Enqueue( updatePaymentStatusTxn ); if ( receiptEmail.HasValue ) { // Queue a transaction to send receipts var newTransactionIds = newTransactions.Select( t => t.Id ).ToList(); var sendPaymentReceiptsTxn = new Rock.Transactions.SendPaymentReceipts( receiptEmail.Value, newTransactionIds ); Rock.Transactions.RockQueue.TransactionQueue.Enqueue( sendPaymentReceiptsTxn ); } } StringBuilder sb = new StringBuilder(); sb.AppendFormat( "<li>{0} {1} downloaded.</li>", totalPayments.ToString( "N0" ), ( totalPayments == 1 ? "payment" : "payments" ) ); if ( totalAlreadyDownloaded > 0 ) { sb.AppendFormat( "<li>{0} {1} previously downloaded and {2} already been added.</li>", totalAlreadyDownloaded.ToString( "N0" ), ( totalAlreadyDownloaded == 1 ? "payment was" : "payments were" ), ( totalAlreadyDownloaded == 1 ? "has" : "have" ) ); } if ( totalStatusChanges > 0 ) { sb.AppendFormat( "<li>{0} {1} previously downloaded but had a change of status.</li>", totalStatusChanges.ToString( "N0" ), ( totalStatusChanges == 1 ? "payment was" : "payments were" ) ); } if ( totalNoScheduledTransaction > 0 ) { sb.AppendFormat( "<li>{0} {1} could not be matched to an existing scheduled payment profile.</li>", totalNoScheduledTransaction.ToString( "N0" ), ( totalNoScheduledTransaction == 1 ? "payment" : "payments" ) ); } sb.AppendFormat( "<li>{0} {1} successfully added.</li>", totalAdded.ToString( "N0" ), ( totalAdded == 1 ? "payment was" : "payments were" ) ); if ( totalReversals > 0 ) { sb.AppendFormat( "<li>{0} {1} added as a reversal to a previous transaction.</li>", totalReversals.ToString( "N0" ), ( totalReversals == 1 ? "payment was" : "payments were" ) ); } if ( totalStatusChanges > 0 ) { sb.AppendFormat( "<li>{0} {1} previously downloaded but had a change of status.</li>", totalStatusChanges.ToString( "N0" ), ( totalStatusChanges == 1 ? "payment was" : "payments were" ) ); } foreach ( var batchItem in batchSummary ) { int items = batchItem.Value.Count; if ( items > 0 ) { var batch = batches .Where( b => b.Guid.Equals( batchItem.Key ) ) .FirstOrDefault(); string batchName = string.Format( "'{0} ({1})'", batch.Name, batch.BatchStartDateTime.Value.ToString( "d" ) ); if ( !string.IsNullOrWhiteSpace( batchUrlFormat ) ) { batchName = string.Format( "<a href='{0}'>{1}</a>", string.Format( batchUrlFormat, batch.Id ), batchName ); } decimal sum = batchItem.Value.Sum(); string summaryformat = items == 1 ? "<li>{0} transaction of {1} was added to the {2} batch.</li>" : "<li>{0} transactions totaling {1} were added to the {2} batch</li>"; sb.AppendFormat( summaryformat, items.ToString( "N0" ), sum.FormatAsCurrency(), batchName ); } } return sb.ToString(); }
/// <summary> /// Handles the Click event of the lbSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void lbSave_Click( object sender, EventArgs e ) { var rockContext = new RockContext(); var txnService = new FinancialTransactionService( rockContext ); var txnDetailService = new FinancialTransactionDetailService( rockContext ); var txnImageService = new FinancialTransactionImageService( rockContext ); var binaryFileService = new BinaryFileService( rockContext ); FinancialTransaction txn = null; int? txnId = hfTransactionId.Value.AsIntegerOrNull(); int? batchId = hfBatchId.Value.AsIntegerOrNull(); if ( txnId.HasValue ) { txn = txnService.Get( txnId.Value ); } if ( txn == null && batchId.HasValue ) { txn = new FinancialTransaction(); txnService.Add( txn ); txn.BatchId = batchId.Value; } if ( txn != null ) { txn.AuthorizedPersonId = ppAuthorizedPerson.PersonId; txn.TransactionDateTime = dtTransactionDateTime.SelectedDateTime; txn.TransactionTypeValueId = ddlTransactionType.SelectedValue.AsInteger(); txn.SourceTypeValueId = ddlSourceType.SelectedValueAsInt(); Guid? gatewayGuid = cpPaymentGateway.SelectedValueAsGuid(); if ( gatewayGuid.HasValue ) { var gatewayEntity = EntityTypeCache.Read( gatewayGuid.Value ); if ( gatewayEntity != null ) { txn.GatewayEntityTypeId = gatewayEntity.Id; } else { txn.GatewayEntityTypeId = null; } } else { txn.GatewayEntityTypeId = null; } txn.TransactionCode = tbTransactionCode.Text; txn.CurrencyTypeValueId = ddlCurrencyType.SelectedValueAsInt(); txn.CreditCardTypeValueId = ddlCreditCardType.SelectedValueAsInt(); txn.Summary = tbSummary.Text; if ( !Page.IsValid || !txn.IsValid ) { return; } foreach ( var txnDetail in TransactionDetailsState ) { if ( !txnDetail.IsValid ) { return; } } foreach ( var txnImage in TransactionImagesState ) { if ( !txnImage.IsValid ) { return; } } rockContext.WrapTransaction( () => { // Save the transaction rockContext.SaveChanges(); // Delete any transaction details that were removed var txnDetailsInDB = txnDetailService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList(); var deletedDetails = from txnDetail in txnDetailsInDB where !TransactionDetailsState.Select( d => d.Guid ).Contains( txnDetail.Guid ) select txnDetail; deletedDetails.ToList().ForEach( txnDetail => { txnDetailService.Delete( txnDetail ); } ); rockContext.SaveChanges(); // Save Transaction Details foreach ( var editorTxnDetail in TransactionDetailsState ) { // Add or Update the activity type var txnDetail = txn.TransactionDetails.FirstOrDefault( d => d.Guid.Equals( editorTxnDetail.Guid ) ); if ( txnDetail == null ) { txnDetail = new FinancialTransactionDetail(); txnDetail.Guid = editorTxnDetail.Guid; txn.TransactionDetails.Add( txnDetail ); } txnDetail.AccountId = editorTxnDetail.AccountId; txnDetail.Amount = editorTxnDetail.Amount; txnDetail.Summary = editorTxnDetail.Summary; } rockContext.SaveChanges(); // Remove any images that do not have a binary file foreach ( var txnImage in TransactionImagesState.Where( i => i.BinaryFileId == 0 ).ToList() ) { TransactionImagesState.Remove( txnImage ); } // Delete any transaction images that were removed var txnImagesInDB = txnImageService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList(); var deletedImages = from txnImage in txnImagesInDB where !TransactionImagesState.Select( d => d.Guid ).Contains( txnImage.Guid ) select txnImage; deletedImages.ToList().ForEach( txnImage => { txnImageService.Delete( txnImage ); } ); rockContext.SaveChanges(); // Save Transaction Images foreach ( var editorTxnImage in TransactionImagesState ) { // Add or Update the activity type var txnImage = txn.Images.FirstOrDefault( d => d.Guid.Equals( editorTxnImage.Guid ) ); if ( txnImage == null ) { txnImage = new FinancialTransactionImage(); txnImage.Guid = editorTxnImage.Guid; txn.Images.Add( txnImage ); } txnImage.BinaryFileId = editorTxnImage.BinaryFileId; txnImage.TransactionImageTypeValueId = editorTxnImage.TransactionImageTypeValueId; } rockContext.SaveChanges(); // Make sure updated binary files are not temporary var savedBinaryFileIds = txn.Images.Select( i => i.BinaryFileId ).ToList(); foreach ( var binaryFile in binaryFileService.Queryable().Where( f => savedBinaryFileIds.Contains( f.Id ) ) ) { binaryFile.IsTemporary = false; } // Delete any orphaned images var orphanedBinaryFileIds = BinaryFileIds.Where( f => !savedBinaryFileIds.Contains( f ) ); foreach ( var binaryFile in binaryFileService.Queryable().Where( f => orphanedBinaryFileIds.Contains( f.Id ) ) ) { binaryFileService.Delete( binaryFile ); } rockContext.SaveChanges(); } ); // Requery the batch to support EF navigation properties var savedTxn = GetTransaction( txn.Id ); ShowReadOnlyDetails( savedTxn ); } }
/// <summary> /// Maps the contribution. /// </summary> /// <param name="tableData">The table data.</param> /// <param name="selectedColumns">The selected columns.</param> private void MapContribution( IQueryable<Row> tableData, List<string> selectedColumns = null ) { var lookupContext = new RockContext(); int transactionEntityTypeId = EntityTypeCache.Read( "Rock.Model.FinancialTransaction" ).Id; var transactionTypeContributionId = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ), lookupContext ).Id; var currencyTypes = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_CURRENCY_TYPE ) ); int currencyTypeACH = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_ACH ) ) ).Id; int currencyTypeCash = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CASH ) ) ).Id; int currencyTypeCheck = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CHECK ) ) ).Id; int currencyTypeCreditCard = currencyTypes.DefinedValues.FirstOrDefault( dv => dv.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) ).Id; int? currencyTypeNonCash = currencyTypes.DefinedValues.Where( dv => dv.Value.Equals( "Non-Cash" ) ).Select( dv => (int?)dv.Id ).FirstOrDefault(); if ( currencyTypeNonCash == null ) { var newTenderNonCash = new DefinedValue(); newTenderNonCash.Value = "Non-Cash"; newTenderNonCash.Description = "Non-Cash"; newTenderNonCash.DefinedTypeId = currencyTypes.Id; lookupContext.DefinedValues.Add( newTenderNonCash ); lookupContext.SaveChanges(); currencyTypeNonCash = newTenderNonCash.Id; } var creditCardTypes = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_CREDIT_CARD_TYPE ) ).DefinedValues; int sourceTypeOnsite = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_ONSITE_COLLECTION ), lookupContext ).Id; int sourceTypeWebsite = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_WEBSITE ), lookupContext ).Id; int sourceTypeKiosk = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.FINANCIAL_SOURCE_TYPE_KIOSK ), lookupContext ).Id; var refundReasons = DefinedTypeCache.Read( new Guid( Rock.SystemGuid.DefinedType.FINANCIAL_TRANSACTION_REFUND_REASON ), lookupContext ).DefinedValues; var accountList = new FinancialAccountService( lookupContext ).Queryable().AsNoTracking().ToList(); int? defaultBatchId = null; if ( ImportedBatches.ContainsKey( 0 ) ) { defaultBatchId = ImportedBatches[0]; } // Get all imported contributions var importedContributions = new FinancialTransactionService( lookupContext ).Queryable().AsNoTracking() .Where( c => c.ForeignId != null ) .ToDictionary( t => (int)t.ForeignId, t => (int?)t.Id ); // List for batching new contributions var newTransactions = new List<FinancialTransaction>(); int completed = 0; int totalRows = tableData.Count(); int percentage = ( totalRows - 1 ) / 100 + 1; ReportProgress( 0, string.Format( "Verifying contribution import ({0:N0} found, {1:N0} already exist).", totalRows, importedContributions.Count ) ); foreach ( var row in tableData.Where( r => r != null ) ) { int? individualId = row["Individual_ID"] as int?; int? householdId = row["Household_ID"] as int?; int? contributionId = row["ContributionID"] as int?; if ( contributionId != null && !importedContributions.ContainsKey( (int)contributionId ) ) { var transaction = new FinancialTransaction(); transaction.CreatedByPersonAliasId = ImportPersonAliasId; transaction.ModifiedByPersonAliasId = ImportPersonAliasId; transaction.TransactionTypeValueId = transactionTypeContributionId; transaction.ForeignKey = contributionId.ToString(); transaction.ForeignId = contributionId; int? giverAliasId = null; var personKeys = GetPersonKeys( individualId, householdId ); if ( personKeys != null && personKeys.PersonAliasId > 0 ) { giverAliasId = personKeys.PersonAliasId; transaction.CreatedByPersonAliasId = giverAliasId; transaction.AuthorizedPersonAliasId = giverAliasId; transaction.ProcessedByPersonAliasId = giverAliasId; } string summary = row["Memo"] as string; if ( summary != null ) { transaction.Summary = summary; } int? batchId = row["BatchID"] as int?; if ( batchId != null && ImportedBatches.Any( b => b.Key.Equals( batchId ) ) ) { transaction.BatchId = ImportedBatches.FirstOrDefault( b => b.Key.Equals( batchId ) ).Value; } else { // use the default batch for any non-matching transactions transaction.BatchId = defaultBatchId; } DateTime? receivedDate = row["Received_Date"] as DateTime?; if ( receivedDate != null ) { transaction.TransactionDateTime = receivedDate; transaction.CreatedDateTime = receivedDate; transaction.ModifiedDateTime = ImportDateTime; } string cardType = row["Card_Type"] as string; string cardLastFour = row["Last_Four"] as string; string contributionType = row["Contribution_Type_Name"].ToStringSafe().ToLower(); if ( contributionType != null ) { // set default source to onsite, exceptions listed below transaction.SourceTypeValueId = sourceTypeOnsite; int? paymentCurrencyTypeId = null, creditCardTypeId = null; if ( contributionType == "cash" ) { paymentCurrencyTypeId = currencyTypeCash; } else if ( contributionType == "check" ) { paymentCurrencyTypeId = currencyTypeCheck; } else if ( contributionType == "ach" ) { paymentCurrencyTypeId = currencyTypeACH; transaction.SourceTypeValueId = sourceTypeWebsite; } else if ( contributionType == "credit card" ) { paymentCurrencyTypeId = currencyTypeCreditCard; transaction.SourceTypeValueId = sourceTypeWebsite; if ( cardType != null ) { creditCardTypeId = creditCardTypes.Where( t => t.Value.Equals( cardType ) ).Select( t => (int?)t.Id ).FirstOrDefault(); } } else { paymentCurrencyTypeId = currencyTypeNonCash; } var paymentDetail = new FinancialPaymentDetail(); paymentDetail.CreatedDateTime = receivedDate; paymentDetail.CreatedByPersonAliasId = giverAliasId; paymentDetail.ModifiedDateTime = ImportDateTime; paymentDetail.ModifiedByPersonAliasId = giverAliasId; paymentDetail.CurrencyTypeValueId = paymentCurrencyTypeId; paymentDetail.CreditCardTypeValueId = creditCardTypeId; paymentDetail.AccountNumberMasked = cardLastFour; paymentDetail.ForeignKey = contributionId.ToString(); paymentDetail.ForeignId = contributionId; transaction.FinancialPaymentDetail = paymentDetail; } string checkNumber = row["Check_Number"] as string; // if the check number is valid, put it in the transaction code if ( checkNumber.AsType<int?>() != null ) { transaction.TransactionCode = checkNumber; } // check for SecureGive kiosk transactions else if ( !string.IsNullOrEmpty( checkNumber ) && checkNumber.StartsWith( "SG" ) ) { transaction.SourceTypeValueId = sourceTypeKiosk; } string fundName = row["Fund_Name"] as string; string subFund = row["Sub_Fund_Name"] as string; string fundGLAccount = row["Fund_GL_Account"] as string; string subFundGLAccount = row["Sub_Fund_GL_Account"] as string; Boolean? isFundActive = row["Fund_Is_active"] as Boolean?; decimal? statedValue = row["Stated_Value"] as decimal?; decimal? amount = row["Amount"] as decimal?; if ( fundName != null & amount != null ) { int transactionAccountId; var parentAccount = accountList.FirstOrDefault( a => a.Name.Equals( fundName ) && a.CampusId == null ); if ( parentAccount == null ) { parentAccount = AddAccount( lookupContext, fundName, fundGLAccount, null, null, isFundActive ); accountList.Add( parentAccount ); } if ( subFund != null ) { int? campusFundId = null; // assign a campus if the subfund is a campus fund var campusFund = CampusList.FirstOrDefault( c => subFund.StartsWith( c.Name ) || subFund.StartsWith( c.ShortCode ) ); if ( campusFund != null ) { // use full campus name as the subfund subFund = campusFund.Name; campusFundId = campusFund.Id; } // add info to easily find/assign this fund in the view subFund = string.Format( "{0} {1}", subFund, fundName ); var childAccount = accountList.FirstOrDefault( c => c.Name.Equals( subFund ) && c.ParentAccountId == parentAccount.Id ); if ( childAccount == null ) { // create a child account with a campusId if it was set childAccount = AddAccount( lookupContext, subFund, subFundGLAccount, campusFundId, parentAccount.Id, isFundActive ); accountList.Add( childAccount ); } transactionAccountId = childAccount.Id; } else { transactionAccountId = parentAccount.Id; } if ( amount == 0 && statedValue != null && statedValue != 0 ) { amount = statedValue; } var transactionDetail = new FinancialTransactionDetail(); transactionDetail.Amount = (decimal)amount; transactionDetail.CreatedDateTime = receivedDate; transactionDetail.AccountId = transactionAccountId; transaction.TransactionDetails.Add( transactionDetail ); if ( amount < 0 ) { transaction.RefundDetails = new FinancialTransactionRefund(); transaction.RefundDetails.CreatedDateTime = receivedDate; transaction.RefundDetails.RefundReasonValueId = refundReasons.Where( dv => summary != null && dv.Value.Contains( summary ) ) .Select( dv => (int?)dv.Id ).FirstOrDefault(); transaction.RefundDetails.RefundReasonSummary = summary; } } newTransactions.Add( transaction ); completed++; if ( completed % percentage < 1 ) { int percentComplete = completed / percentage; ReportProgress( percentComplete, string.Format( "{0:N0} contributions imported ({1}% complete).", completed, percentComplete ) ); } else if ( completed % ReportingNumber < 1 ) { SaveContributions( newTransactions ); newTransactions.Clear(); ReportPartialProgress(); } } } if ( newTransactions.Any() ) { SaveContributions( newTransactions ); } ReportProgress( 100, string.Format( "Finished contribution import: {0:N0} contributions imported.", completed ) ); }
/// <summary> /// Shows the read only details. /// </summary> /// <param name="txn">The TXN.</param> private void ShowReadOnlyDetails( FinancialTransaction txn ) { SetEditMode( false ); if ( txn != null ) { hfTransactionId.Value = txn.Id.ToString(); SetHeadingInfo( txn ); string rockUrlRoot = ResolveRockUrl( "/" ); var detailsLeft = new DescriptionList() .Add( "Person", txn.AuthorizedPerson != null ? txn.AuthorizedPerson.GetAnchorTag( rockUrlRoot ) : string.Empty ) .Add( "Amount", ( txn.TransactionDetails.Sum( d => (decimal?)d.Amount ) ?? 0.0M ).ToString( "C2" ) ) .Add( "Date/Time", txn.TransactionDateTime.HasValue ? txn.TransactionDateTime.Value.ToString( "g" ) : string.Empty ); if ( txn.Batch != null ) { var qryParam = new Dictionary<string, string>(); qryParam.Add( "BatchId", txn.Batch.Id.ToString() ); string url = LinkedPageUrl( "BatchDetailPage", qryParam ); detailsLeft.Add( "Batch", !string.IsNullOrWhiteSpace( url ) ? string.Format( "<a href='{0}'>{1}</a>", url, txn.Batch.Name ) : txn.Batch.Name ); } detailsLeft.Add( "Source", txn.SourceTypeValue != null ? txn.SourceTypeValue.Value : string.Empty ); if ( txn.GatewayEntityType != null ) { detailsLeft.Add( "Payment Gateway", Rock.Financial.GatewayContainer.GetComponentName( txn.GatewayEntityType.Name ) ); } detailsLeft.Add( "Transaction Code", txn.TransactionCode ); if ( txn.ScheduledTransaction != null ) { var qryParam = new Dictionary<string, string>(); qryParam.Add( "ScheduledTransactionId", txn.ScheduledTransaction.Id.ToString() ); string url = LinkedPageUrl( "ScheduledTransactionDetailPage", qryParam ); detailsLeft.Add( "Scheduled Transaction Id", !string.IsNullOrWhiteSpace( url ) ? string.Format( "<a href='{0}'>{1}</a>", url, txn.ScheduledTransaction.GatewayScheduleId ) : txn.ScheduledTransaction.GatewayScheduleId ); } if ( txn.CurrencyTypeValue != null ) { string currencyType = txn.CurrencyTypeValue.Value; if ( txn.CurrencyTypeValue.Guid.Equals( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD.AsGuid() ) ) { currencyType += txn.CreditCardTypeValue != null ? ( " - " + txn.CreditCardTypeValue.Value ) : string.Empty; } detailsLeft.Add( "Currency Type", currencyType ); } detailsLeft.Add( "Summary", txn.Summary ); var modified = new StringBuilder(); ; if ( txn.CreatedByPersonAlias != null && txn.CreatedByPersonAlias.Person != null && txn.CreatedDateTime.HasValue ) { modified.AppendFormat( "Created by {0} on {1} at {2}<br/>", txn.CreatedByPersonAlias.Person.GetAnchorTag( rockUrlRoot ), txn.CreatedDateTime.Value.ToShortDateString(), txn.CreatedDateTime.Value.ToShortTimeString() ); } if ( txn.ProcessedByPersonAlias != null && txn.ProcessedByPersonAlias.Person != null && txn.ProcessedDateTime.HasValue ) { modified.AppendFormat( "Processed by {0} on {1} at {2}<br/>", txn.ProcessedByPersonAlias.Person.GetAnchorTag( rockUrlRoot ), txn.ProcessedDateTime.Value.ToShortDateString(), txn.ProcessedDateTime.Value.ToShortTimeString() ); } if ( txn.ModifiedByPersonAlias != null && txn.ModifiedByPersonAlias.Person != null && txn.ModifiedDateTime.HasValue ) { modified.AppendFormat( "Last Modified by {0} on {1} at {2}<br/>", txn.ModifiedByPersonAlias.Person.GetAnchorTag( rockUrlRoot ), txn.ModifiedDateTime.Value.ToShortDateString(), txn.ModifiedDateTime.Value.ToShortTimeString() ); } detailsLeft.Add( "Updates", modified.ToString() ); lDetailsLeft.Text = detailsLeft.Html; gAccountsView.DataSource = txn.TransactionDetails.ToList(); gAccountsView.DataBind(); if ( txn.Images.Any() ) { var primaryImage = txn.Images .OrderBy( i => i.TransactionImageTypeValue.Order ) .FirstOrDefault(); imgPrimary.ImageUrl = string.Format( "~/GetImage.ashx?id={0}", primaryImage.BinaryFileId ); imgPrimary.Visible = true; rptrImages.DataSource = txn.Images .Where( i => !i.Id.Equals( primaryImage.Id ) ) .OrderBy( i => i.TransactionImageTypeValue.Order ) .ToList(); rptrImages.DataBind(); } else { imgPrimary.Visible = false; } } }
/// <summary> /// Shows the edit details. /// </summary> /// <param name="txn">The TXN.</param> private void ShowEditDetails( FinancialTransaction txn, RockContext rockContext ) { if ( txn != null ) { BindDropdowns( rockContext ); hfTransactionId.Value = txn.Id.ToString(); SetHeadingInfo( txn ); SetEditMode( true ); ppAuthorizedPerson.SetValue( txn.AuthorizedPerson ); dtTransactionDateTime.SelectedDateTime = txn.TransactionDateTime; ddlTransactionType.SetValue( txn.TransactionTypeValueId ); ddlSourceType.SetValue( txn.SourceTypeValueId ); cpPaymentGateway.SetValue( txn.GatewayEntityType != null ? txn.GatewayEntityType.Guid.ToString().ToUpper() : string.Empty ); tbTransactionCode.Text = txn.TransactionCode; ddlCurrencyType.SetValue( txn.CurrencyTypeValueId ); ddlCreditCardType.SetValue( txn.CreditCardTypeValueId ); SetCreditCardVisibility(); TransactionDetailsState = txn.TransactionDetails.ToList(); TransactionImagesState = txn.Images.ToList(); BindAccountsEditGrid(); tbSummary.Text = txn.Summary; BinaryFileIds = txn.Images.Select( i => i.BinaryFileId ).ToList(); BindImages(); } }
/// <summary> /// Sets the heading information. /// </summary> /// <param name="txn">The TXN.</param> private void SetHeadingInfo( FinancialTransaction txn ) { if ( txn.TransactionTypeValue != null ) { hlType.Visible = true; hlType.Text = txn.TransactionTypeValue.Value; } else { hlType.Visible = false; } }
private void SaveTransaction( FinancialGateway financialGateway, GatewayComponent gateway, Person person, PaymentInfo paymentInfo, FinancialTransaction transaction, RockContext rockContext ) { var txnChanges = new List<string>(); txnChanges.Add( "Created Transaction" ); History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode ); transaction.AuthorizedPersonAliasId = person.PrimaryAliasId; History.EvaluateChange( txnChanges, "Person", string.Empty, person.FullName ); transaction.TransactionDateTime = RockDateTime.Now; History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime ); transaction.FinancialGatewayId = financialGateway.Id; History.EvaluateChange( txnChanges, "Gateway", string.Empty, financialGateway.Name ); var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_CONTRIBUTION ) ); transaction.TransactionTypeValueId = txnType.Id; History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value ); transaction.Summary = paymentInfo.Comment1; History.EvaluateChange( txnChanges, "Summary", string.Empty, transaction.Summary ); if ( transaction.FinancialPaymentDetail == null ) { transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); } transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges ); Guid sourceGuid = Guid.Empty; if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) ) { var source = DefinedValueCache.Read( sourceGuid ); if ( source != null ) { transaction.SourceTypeValueId = source.Id; History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value ); } } foreach ( var account in SelectedAccounts.Where( a => a.Amount > 0 ) ) { var transactionDetail = new FinancialTransactionDetail(); transactionDetail.Amount = account.Amount; transactionDetail.AccountId = account.Id; transaction.TransactionDetails.Add( transactionDetail ); History.EvaluateChange( txnChanges, account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() ); } var batchService = new FinancialBatchService( rockContext ); // Get the batch var batch = batchService.Get( GetAttributeValue( "BatchNamePrefix" ), paymentInfo.CurrencyTypeValue, paymentInfo.CreditCardTypeValue, transaction.TransactionDateTime.Value, financialGateway.GetBatchTimeOffset() ); var batchChanges = new List<string>(); if ( batch.Id == 0 ) { batchChanges.Add( "Generated the batch" ); History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name ); History.EvaluateChange( batchChanges, "Status", null, batch.Status ); History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime ); History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime ); } decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount; History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() ); batch.ControlAmount = newControlAmount; transaction.BatchId = batch.Id; batch.Transactions.Add( transaction ); rockContext.SaveChanges(); HistoryService.SaveChanges( rockContext, typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), batch.Id, batchChanges ); HistoryService.SaveChanges( rockContext, typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), batch.Id, txnChanges, person.FullName, typeof( FinancialTransaction ), transaction.Id ); SendReceipt( transaction.Id ); TransactionCode = transaction.TransactionCode; }
/// <summary> /// Handles the Click event of the lbSave control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> protected void lbSave_Click( object sender, EventArgs e ) { var rockContext = new RockContext(); var txnService = new FinancialTransactionService( rockContext ); var txnDetailService = new FinancialTransactionDetailService( rockContext ); var txnImageService = new FinancialTransactionImageService( rockContext ); var binaryFileService = new BinaryFileService( rockContext ); FinancialTransaction txn = null; int? txnId = hfTransactionId.Value.AsIntegerOrNull(); int? batchId = hfBatchId.Value.AsIntegerOrNull(); if ( txnId.HasValue ) { txn = txnService.Get( txnId.Value ); } if ( txn == null ) { txn = new FinancialTransaction(); txnService.Add( txn ); txn.BatchId = batchId; } if ( txn != null ) { if ( ppAuthorizedPerson.PersonId.HasValue ) { txn.AuthorizedPersonAliasId = ppAuthorizedPerson.PersonAliasId; } txn.TransactionDateTime = dtTransactionDateTime.SelectedDateTime; txn.TransactionTypeValueId = ddlTransactionType.SelectedValue.AsInteger(); txn.SourceTypeValueId = ddlSourceType.SelectedValueAsInt(); Guid? gatewayGuid = cpPaymentGateway.SelectedValueAsGuid(); if ( gatewayGuid.HasValue ) { var gatewayEntity = EntityTypeCache.Read( gatewayGuid.Value ); if ( gatewayEntity != null ) { txn.GatewayEntityTypeId = gatewayEntity.Id; } else { txn.GatewayEntityTypeId = null; } } else { txn.GatewayEntityTypeId = null; } txn.TransactionCode = tbTransactionCode.Text; txn.CurrencyTypeValueId = ddlCurrencyType.SelectedValueAsInt(); txn.CreditCardTypeValueId = ddlCreditCardType.SelectedValueAsInt(); txn.Summary = tbSummary.Text; if ( !Page.IsValid || !txn.IsValid ) { return; } foreach ( var txnDetail in TransactionDetailsState ) { if ( !txnDetail.IsValid ) { return; } } rockContext.WrapTransaction( () => { // Save the transaction rockContext.SaveChanges(); // Delete any transaction details that were removed var txnDetailsInDB = txnDetailService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList(); var deletedDetails = from txnDetail in txnDetailsInDB where !TransactionDetailsState.Select( d => d.Guid ).Contains( txnDetail.Guid ) select txnDetail; deletedDetails.ToList().ForEach( txnDetail => { txnDetailService.Delete( txnDetail ); } ); rockContext.SaveChanges(); // Save Transaction Details foreach ( var editorTxnDetail in TransactionDetailsState ) { // Add or Update the activity type var txnDetail = txn.TransactionDetails.FirstOrDefault( d => d.Guid.Equals( editorTxnDetail.Guid ) ); if ( txnDetail == null ) { txnDetail = new FinancialTransactionDetail(); txnDetail.Guid = editorTxnDetail.Guid; txn.TransactionDetails.Add( txnDetail ); } txnDetail.AccountId = editorTxnDetail.AccountId; txnDetail.Amount = UseSimpleAccountMode ? tbSingleAccountAmount.Text.AsDecimal() : editorTxnDetail.Amount; txnDetail.Summary = editorTxnDetail.Summary; } rockContext.SaveChanges(); // Delete any transaction images that were removed var orphanedBinaryFileIds = new List<int>(); var txnImagesInDB = txnImageService.Queryable().Where( a => a.TransactionId.Equals( txn.Id ) ).ToList(); foreach ( var txnImage in txnImagesInDB.Where( i => !TransactionImagesState.Contains( i.BinaryFileId ) ) ) { orphanedBinaryFileIds.Add( txnImage.BinaryFileId ); txnImageService.Delete( txnImage ); } // Save Transaction Images int imageOrder = 0; foreach ( var binaryFileId in TransactionImagesState ) { // Add or Update the activity type var txnImage = txnImagesInDB.FirstOrDefault( i => i.BinaryFileId == binaryFileId ); if ( txnImage == null ) { txnImage = new FinancialTransactionImage(); txnImage.TransactionId = txn.Id; txn.Images.Add( txnImage ); } txnImage.BinaryFileId = binaryFileId; txnImage.Order = imageOrder; imageOrder++; } rockContext.SaveChanges(); // Make sure updated binary files are not temporary foreach ( var binaryFile in binaryFileService.Queryable().Where( f => TransactionImagesState.Contains( f.Id ) ) ) { binaryFile.IsTemporary = false; } // Delete any orphaned images foreach ( var binaryFile in binaryFileService.Queryable().Where( f => orphanedBinaryFileIds.Contains( f.Id ) ) ) { binaryFileService.Delete( binaryFile ); } rockContext.SaveChanges(); } ); // Save selected options to session state in order to prefill values for next added txn Session["NewTxnDefault_BatchId"] = txn.BatchId; Session["NewTxnDefault_TransactionDateTime"] = txn.TransactionDateTime; Session["NewTxnDefault_TransactionType"] = txn.TransactionTypeValueId; Session["NewTxnDefault_SourceType"] = txn.SourceTypeValueId; Session["NewTxnDefault_CurrencyType"] = txn.CurrencyTypeValueId; Session["NewTxnDefault_CreditCardType"] = txn.CreditCardTypeValueId; if ( TransactionDetailsState.Count() == 1 ) { Session["NewTxnDefault_Account"] = TransactionDetailsState.First().AccountId; } else { Session.Remove("NewTxnDefault_Account"); } // Requery the batch to support EF navigation properties var savedTxn = GetTransaction( txn.Id ); ShowReadOnlyDetails( savedTxn ); } }
/// <summary> /// Formats the summary. /// </summary> /// <param name="txn">The TXN.</param> /// <returns></returns> private string FormatSummary( FinancialTransaction txn ) { var sb = new StringBuilder(); foreach ( var transactionDetail in txn.TransactionDetails ) { sb.AppendFormat( "{0} ({2}{1})<br>", transactionDetail.Account, transactionDetail.Amount, GlobalAttributesCache.Value( "CurrencySymbol" ) ); } return sb.ToString(); }
/// <summary> /// Shows the edit details. /// </summary> /// <param name="txn">The TXN.</param> private void ShowEditDetails( FinancialTransaction txn, RockContext rockContext ) { this.Page.ClientScript.RegisterStartupScript( this.GetType(), "StartupScript", @"Sys.Application.add_load(function () { // if the person picker is empty then open it for quick entry var personPicker = $('.js-authorizedperson'); var currentPerson = personPicker.find('.picker-selectedperson').html(); if (currentPerson != null && currentPerson.length == 0) { $(personPicker).find('a.picker-label').trigger('click'); } });", true ); if ( txn != null ) { BindDropdowns( rockContext ); hfTransactionId.Value = txn.Id.ToString(); SetHeadingInfo( txn ); SetEditMode( true ); if ( txn.AuthorizedPersonAlias != null ) { ppAuthorizedPerson.SetValue( txn.AuthorizedPersonAlias.Person ); } else { ppAuthorizedPerson.SetValue( null ); } dtTransactionDateTime.SelectedDateTime = txn.TransactionDateTime; ddlTransactionType.SetValue( txn.TransactionTypeValueId ); ddlSourceType.SetValue( txn.SourceTypeValueId ); cpPaymentGateway.SetValue( txn.GatewayEntityType != null ? txn.GatewayEntityType.Guid.ToString().ToUpper() : string.Empty ); tbTransactionCode.Text = txn.TransactionCode; ddlCurrencyType.SetValue( txn.CurrencyTypeValueId ); ddlCreditCardType.SetValue( txn.CreditCardTypeValueId ); SetCreditCardVisibility(); TransactionDetailsState = txn.TransactionDetails.ToList(); TransactionImagesState = txn.Images.OrderBy( i => i.Order ).Select( i => i.BinaryFileId ).ToList(); if ( TransactionDetailsState.Count() == 1 ) { UseSimpleAccountMode = true; } else { UseSimpleAccountMode = false; } BindAccounts(); tbSummary.Text = txn.Summary; BindImages(); } }
/// <summary> /// Charges the specified payment info. /// </summary> /// <param name="paymentInfo">The payment info.</param> /// <param name="errorMessage">The error message.</param> /// <returns></returns> public override FinancialTransaction Charge( FinancialGateway financialGateway, PaymentInfo paymentInfo, out string errorMessage ) { errorMessage = string.Empty; RequestMessage request = GetPaymentInfo( financialGateway, paymentInfo ); if ( request == null ) { errorMessage = "Payment type not implemented"; return null; } request.purchaseTotals = GetTotals(); request.billTo = GetBillTo( paymentInfo ); request.item = GetItems( paymentInfo ); if ( !paymentInfo.CurrencyTypeValue.Guid.Equals( new Guid( Rock.SystemGuid.DefinedValue.CURRENCY_TYPE_CREDIT_CARD ) ) ) { request.ecDebitService = new ECDebitService(); request.ecDebitService.commerceIndicator = "internet"; request.ecDebitService.run = "true"; } else { request.ccAuthService = new CCAuthService(); request.ccAuthService.commerceIndicator = "internet"; request.ccAuthService.run = "true"; request.ccCaptureService = new CCCaptureService(); request.ccCaptureService.run = "true"; } // Charge the transaction ReplyMessage reply = SubmitTransaction( financialGateway, request, out errorMessage ); if ( reply != null && reply.reasonCode.Equals( GATEWAY_RESPONSE_SUCCESS ) ) { var transactionGuid = new Guid( reply.merchantReferenceCode ); var transaction = new FinancialTransaction { Guid = transactionGuid }; transaction.TransactionCode = reply.requestID; return transaction; } else if ( string.IsNullOrEmpty( errorMessage ) ) { errorMessage = string.Format( "Unable to process this order.{0}", ProcessError( reply ) ); } return null; }
/// <summary> /// Shows the detail. /// </summary> /// <param name="transactionId">The transaction identifier.</param> public void ShowDetail( int transactionId, int? batchId ) { // show or hide the add new transaction button depending if there is a batch id in the querystring lbAddTransaction.Visible = !string.IsNullOrWhiteSpace( PageParameter( "batchId" ) ); FinancialTransaction txn = null; bool editAllowed = UserCanEdit; var rockContext = new RockContext(); if ( !transactionId.Equals( 0 ) ) { txn = GetTransaction( transactionId, rockContext ); if ( !editAllowed && txn != null ) { editAllowed = txn.IsAuthorized( Authorization.EDIT, CurrentPerson ); } } if ( txn == null ) { txn = new FinancialTransaction { Id = 0 }; txn.BatchId = batchId; // Hide processor fields when adding a new transaction cpPaymentGateway.Visible = false; tbTransactionCode.Visible = false; // Set values based on previously saved txn values int prevBatchId = Session["NewTxnDefault_BatchId"] as int? ?? 0; if ( prevBatchId == batchId ) { txn.TransactionDateTime = Session["NewTxnDefault_TransactionDateTime"] as DateTime?; txn.TransactionTypeValueId = Session["NewTxnDefault_TransactionType"] as int? ?? 0; txn.SourceTypeValueId = Session["NewTxnDefault_SourceType"] as int?; txn.CurrencyTypeValueId = Session["NewTxnDefault_CurrencyType"] as int?; txn.CreditCardTypeValueId = Session["NewTxnDefault_CreditCardType"] as int?; int? accountId = Session["NewTxnDefault_Account"] as int?; if ( accountId.HasValue ) { var txnDetail = new FinancialTransactionDetail(); txnDetail.AccountId = accountId.Value; txn.TransactionDetails.Add( txnDetail ); } } } else { cpPaymentGateway.Visible = true; tbTransactionCode.Visible = true; } hfTransactionId.Value = txn.Id.ToString(); hfBatchId.Value = batchId.HasValue ? batchId.Value.ToString() : string.Empty; bool readOnly = false; nbEditModeMessage.Text = string.Empty; if ( !editAllowed ) { readOnly = true; nbEditModeMessage.Text = EditModeMessage.ReadOnlyEditActionNotAllowed( FinancialTransaction.FriendlyTypeName ); lbEdit.Visible = false; lbAddTransaction.Visible = false; } else { lbEdit.Visible = true; lbAddTransaction.Visible = true; } if ( readOnly ) { ShowReadOnlyDetails( txn ); } else { if ( txn.Id > 0 ) { ShowReadOnlyDetails( txn ); } else { ShowEditDetails( txn, rockContext ); } } lbSave.Visible = !readOnly; }
private void LaunchWorkflow( WorkflowType workflowType, FinancialTransaction transaction ) { if ( workflowType != null ) { using ( var rockContext = new RockContext() ) { string workflowName = transaction.TransactionCode; if ( transaction.AuthorizedPersonAliasId != null ) { var person = new PersonAliasService( rockContext ).GetPerson( transaction.AuthorizedPersonAliasId.Value ); if ( person != null ) { workflowName = person.FullName; } } var workflowService = new WorkflowService( rockContext ); var workflow = Rock.Model.Workflow.Activate( workflowType, workflowName, rockContext ); if ( workflow != null ) { List<string> workflowErrors; workflowService.Process( workflow, transaction, out workflowErrors ); } } } }
private bool SaveTransaction( GatewayComponent gateway, Registration registration, FinancialTransaction transaction, PaymentInfo paymentInfo, RockContext rockContext ) { if ( transaction != null ) { var txnChanges = new List<string>(); txnChanges.Add( "Created Transaction" ); History.EvaluateChange( txnChanges, "Transaction Code", string.Empty, transaction.TransactionCode ); transaction.AuthorizedPersonAliasId = registration.PersonAliasId; transaction.TransactionDateTime = RockDateTime.Now; History.EvaluateChange( txnChanges, "Date/Time", null, transaction.TransactionDateTime ); transaction.FinancialGatewayId = RegistrationTemplate.FinancialGatewayId; History.EvaluateChange( txnChanges, "Gateway", string.Empty, RegistrationTemplate.FinancialGateway.Name ); var txnType = DefinedValueCache.Read( new Guid( Rock.SystemGuid.DefinedValue.TRANSACTION_TYPE_EVENT_REGISTRATION ) ); transaction.TransactionTypeValueId = txnType.Id; History.EvaluateChange( txnChanges, "Type", string.Empty, txnType.Value ); if ( transaction.FinancialPaymentDetail == null ) { transaction.FinancialPaymentDetail = new FinancialPaymentDetail(); } DefinedValueCache currencyType = null; DefinedValueCache creditCardType = null; if ( paymentInfo != null ) { transaction.FinancialPaymentDetail.SetFromPaymentInfo( paymentInfo, gateway, rockContext, txnChanges ); currencyType = paymentInfo.CurrencyTypeValue; creditCardType = paymentInfo.CreditCardTypeValue; } Guid sourceGuid = Guid.Empty; if ( Guid.TryParse( GetAttributeValue( "Source" ), out sourceGuid ) ) { var source = DefinedValueCache.Read( sourceGuid ); if ( source != null ) { transaction.SourceTypeValueId = source.Id; History.EvaluateChange( txnChanges, "Source", string.Empty, source.Value ); } } transaction.Summary = registration.GetSummary( RegistrationInstanceState ); var transactionDetail = new FinancialTransactionDetail(); transactionDetail.Amount = RegistrationState.PaymentAmount ?? 0.0m; transactionDetail.AccountId = RegistrationInstanceState.AccountId.Value; transactionDetail.EntityTypeId = EntityTypeCache.Read( typeof( Rock.Model.Registration ) ).Id; transactionDetail.EntityId = registration.Id; transaction.TransactionDetails.Add( transactionDetail ); History.EvaluateChange( txnChanges, RegistrationInstanceState.Account.Name, 0.0M.FormatAsCurrency(), transactionDetail.Amount.FormatAsCurrency() ); var batchChanges = new List<string>(); rockContext.WrapTransaction( () => { var batchService = new FinancialBatchService( rockContext ); // determine batch prefix string batchPrefix = string.Empty; if ( !string.IsNullOrWhiteSpace( RegistrationTemplate.BatchNamePrefix ) ) { batchPrefix = RegistrationTemplate.BatchNamePrefix; } else { batchPrefix = GetAttributeValue( "BatchNamePrefix" ); } // Get the batch var batch = batchService.Get( batchPrefix, currencyType, creditCardType, transaction.TransactionDateTime.Value, RegistrationTemplate.FinancialGateway.GetBatchTimeOffset() ); if ( batch.Id == 0 ) { batchChanges.Add( "Generated the batch" ); History.EvaluateChange( batchChanges, "Batch Name", string.Empty, batch.Name ); History.EvaluateChange( batchChanges, "Status", null, batch.Status ); History.EvaluateChange( batchChanges, "Start Date/Time", null, batch.BatchStartDateTime ); History.EvaluateChange( batchChanges, "End Date/Time", null, batch.BatchEndDateTime ); } decimal newControlAmount = batch.ControlAmount + transaction.TotalAmount; History.EvaluateChange( batchChanges, "Control Amount", batch.ControlAmount.FormatAsCurrency(), newControlAmount.FormatAsCurrency() ); batch.ControlAmount = newControlAmount; transaction.BatchId = batch.Id; batch.Transactions.Add( transaction ); rockContext.SaveChanges(); } ); if ( transaction.BatchId.HasValue ) { Task.Run( () => HistoryService.SaveChanges( new RockContext(), typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_BATCH.AsGuid(), transaction.BatchId.Value, batchChanges, true, CurrentPersonAliasId ) ); Task.Run( () => HistoryService.SaveChanges( new RockContext(), typeof( FinancialBatch ), Rock.SystemGuid.Category.HISTORY_FINANCIAL_TRANSACTION.AsGuid(), transaction.BatchId.Value, txnChanges, CurrentPerson != null ? CurrentPerson.FullName : string.Empty, typeof( FinancialTransaction ), transaction.Id, true, CurrentPersonAliasId ) ); } List<string> registrationChanges = new List<string>(); registrationChanges.Add( string.Format( "Made {0} payment", transaction.TotalAmount.FormatAsCurrency() ) ); Task.Run( () => HistoryService.SaveChanges( new RockContext(), typeof( Registration ), Rock.SystemGuid.Category.HISTORY_EVENT_REGISTRATION.AsGuid(), registration.Id, registrationChanges, true, CurrentPersonAliasId ) ); TransactionCode = transaction.TransactionCode; return true; } else { return false; } }