public void TestDonationTotalReturnsExpectedResult() { #region Arrange var transaction = GetValid(9); transaction.Amount = 3m; var donationTransaction = new Transaction(transaction.Item); donationTransaction.Donation = true; donationTransaction.Amount = 10.00m; var donationTransaction2 = new Transaction(transaction.Item); donationTransaction2.Donation = true; donationTransaction2.Amount = 15.00m; var donationTransaction3 = new Transaction(transaction.Item); donationTransaction3.Donation = false; donationTransaction3.Amount = 11.00m; transaction.AddChildTransaction(donationTransaction); transaction.AddChildTransaction(donationTransaction2); transaction.AddChildTransaction(donationTransaction3); #endregion Arrange #region Act var result = transaction.DonationTotal; #endregion Act #region Assert Assert.AreEqual(25, result); #endregion Assert }
public void TestChildTransactionsAreCascadedWithSave() { #region Arrange var transaction = GetValid(9); transaction.Amount = 5m; var donationTransaction = new Transaction(transaction.Item); donationTransaction.Donation = true; donationTransaction.Amount = 10.00m; var donationTransaction2 = new Transaction(transaction.Item); donationTransaction2.Donation = true; donationTransaction2.Amount = 15.00m; transaction.AddChildTransaction(donationTransaction); transaction.AddChildTransaction(donationTransaction2); Assert.AreEqual(5, TransactionRepository.GetAll().Count); #endregion Arrange #region Act TransactionRepository.DbContext.BeginTransaction(); TransactionRepository.EnsurePersistent(transaction); TransactionRepository.DbContext.CommitTransaction(); #endregion Act #region Assert Assert.AreEqual(25.0m, TransactionRepository.GetAll().Where(a => a.ParentTransaction == transaction).Sum(s => s.Amount)); Assert.AreEqual(8, TransactionRepository.GetAll().Count); Assert.IsFalse(transaction.IsTransient()); Assert.IsTrue(transaction.IsValid()); #endregion Assert }
public void TestCorrectionAmountSaves() { #region Arrange var transaction = GetValid(9); transaction.Amount = 1m; var donationTransaction = new Transaction(transaction.Item); donationTransaction.Donation = true; donationTransaction.Amount = 10.00m; var donationTransaction2 = new Transaction(transaction.Item); donationTransaction2.Donation = true; donationTransaction2.Amount = 15.00m; transaction.AddChildTransaction(donationTransaction); transaction.AddChildTransaction(donationTransaction2); var correction = new Transaction(transaction.Item); correction.Donation = false; correction.Amount = -15.00m; correction.CreatedBy = "Test"; transaction.AddChildTransaction(correction); #endregion Arrange #region Act TransactionRepository.DbContext.BeginTransaction(); TransactionRepository.EnsurePersistent(transaction); TransactionRepository.DbContext.CommitTransaction(); #endregion Act #region Assert Assert.AreEqual(3, TransactionRepository.GetAll().Where(a => a.ParentTransaction == transaction).Count()); Assert.IsFalse(transaction.IsTransient()); Assert.IsTrue(transaction.IsValid()); Assert.AreEqual(-15m, transaction.CorrectionTotal); Assert.AreEqual(11m, transaction.Total); #endregion Assert }
/// <summary> /// Create a new quantity answer. /// </summary> /// <param name="transaction"></param> /// <param name="questionSet"></param> /// <param name="question"></param> /// <param name="answer"></param> /// <param name="quantityId">Leave null if creating a new quantity sequence</param> public QuantityAnswer(Transaction transaction, QuestionSet questionSet, Question question, string answer, Guid? quantityId) { Transaction = transaction; QuestionSet = questionSet; Question = question; Answer = answer; QuantityId = quantityId ?? Guid.NewGuid(); QuantityIdNotEmpty = false; }
public virtual void AddChildTransaction(Transaction transaction) { transaction.ParentTransaction = this; transaction.Check = Check; transaction.Credit = Credit; ChildTransactions.Add(transaction); }
public void TestChildTransactionsWithValidValueSaves() { #region Arrange var transaction = GetValid(9); var donationTransaction = new Transaction(transaction.Item); donationTransaction.Donation = true; donationTransaction.Amount = 10.00m; transaction.AddChildTransaction(donationTransaction); #endregion Arrange #region Act TransactionRepository.DbContext.BeginTransaction(); TransactionRepository.EnsurePersistent(transaction); TransactionRepository.DbContext.CommitTransaction(); #endregion Act #region Assert Assert.AreEqual(1, TransactionRepository.GetAll().Where(a => a.ParentTransaction == transaction).Count()); Assert.IsFalse(transaction.IsTransient()); Assert.IsTrue(transaction.IsValid()); #endregion Assert }
/// <summary> /// Extract the requested value from the transaction answers /// </summary> /// <param name="itemReportColumn"></param> /// <param name="transaction"></param> /// <param name="quantityId"></param> /// <returns></returns> private static string ExtractValue(ItemReportColumn itemReportColumn, Transaction transaction, Guid? quantityId) { var result = string.Empty; if (itemReportColumn.Transaction) { var transactionAnswer = transaction.TransactionAnswers.Where(a => a.Question.Name == itemReportColumn.Name && a.QuestionSet == itemReportColumn.QuestionSet).FirstOrDefault(); if (transactionAnswer != null) { result = transactionAnswer.Answer; } } else if (itemReportColumn.Quantity) { var quantityAnswer = transaction.QuantityAnswers.Where(a => a.QuantityId == quantityId.Value && a.Question.Name == itemReportColumn.Name && a.QuestionSet == itemReportColumn.QuestionSet).FirstOrDefault(); if (quantityAnswer != null) { result = quantityAnswer.Answer; } } else if (itemReportColumn.Property) { if (itemReportColumn.Name == StaticValues.Report_DonationTotal) { result = transaction.DonationTotal.ToString("C"); } else if (itemReportColumn.Name == StaticValues.Report_TransactionNumber) { result = transaction.TransactionNumber; } else if (itemReportColumn.Name == StaticValues.Report_TransactionDate) { result = transaction.TransactionDate.ToString(); } else if (itemReportColumn.Name == StaticValues.Report_Active) { result = transaction.IsActive.ToString(); } else if(itemReportColumn.Name == StaticValues.Report_AmountTotal) { result = transaction.AmountTotal.ToString("C"); } else if (itemReportColumn.Name == StaticValues.Report_Total) { result = transaction.Total.ToString("C"); } else if (itemReportColumn.Name == StaticValues.Report_PaymentType) { result = transaction.Credit ? "Credit Card" : "Check"; } else if (itemReportColumn.Name == StaticValues.Report_Quantity) { result = transaction.Quantity.ToString(); } else if (itemReportColumn.Name == StaticValues.Report_Paid) { result = transaction.Paid.ToString(); } else if (itemReportColumn.Name == StaticValues.Report_TotalPaid) { result = transaction.TotalPaid.ToString("C"); } else if (itemReportColumn.Name == StaticValues.Report_RefundIssued) { result = transaction.RefundIssued.ToString(); } else if (itemReportColumn.Name == StaticValues.Report_RefundAmount) { result = transaction.RefundAmount.ToString("C"); } else if (itemReportColumn.Name == StaticValues.Report_Notified) { result = transaction.Notified.ToString(); } else if (itemReportColumn.Name == StaticValues.Report_NotifiedDate) { result = transaction.NotifiedDate == null ? string.Empty : transaction.NotifiedDate.ToString(); } else if (itemReportColumn.Name == StaticValues.Report_TransactionGuid) { if (transaction.Credit) result = string.Format("{0} FID={1}", transaction.TransactionGuid, transaction.FidUsed ?? transaction.Item.TouchnetFID); else result = "n/a"; } } if (result != null && itemReportColumn.Format == StaticValues.FormatCapitalize) { result = UCDArch.Core.Utils.Inflector.Capitalize(result); } return result; }
/// <summary> /// Sends the confirmation. /// </summary> /// <param name="repository">The repository.</param> /// <param name="transaction">The transaction.</param> /// <param name="emailAddress">The email address.</param> public void SendConfirmation(IRepository repository, Transaction transaction, string emailAddress) { Check.Require(transaction != null, "Transaction is required."); Check.Require(!string.IsNullOrEmpty(emailAddress), "Email address is required."); var body = string.Empty; if(transaction.Item != null && transaction.Item.Template != null) { body = transaction.Item.Template.Text; } else { body = repository.OfType<Template>().Queryable.Where(a => a.Default).FirstOrDefault().Text ?? string.Empty; } if (body.Contains(StaticValues.ConfirmationTemplateDelimiter)) { var delimiter = new string[] { StaticValues.ConfirmationTemplateDelimiter }; var parse = body.Split(delimiter, StringSplitOptions.None); //if(transaction.Paid && transaction.TotalPaid > 0) if (transaction.TotalPaid > 0) { body = parse[0]; } else { body = parse[1]; } } string extraSubject; if(transaction.TotalPaid > 0) { if (transaction.Paid) { extraSubject = "Payment confirmed"; } else { extraSubject = "Payment pending"; } } else { extraSubject = "Order confirmed"; } var subject = extraSubject; if (transaction.Item != null && transaction.Item.Name != null) { subject = transaction.Item.Name.Trim() + ": " + extraSubject; } //Things to replace in the body: //Contact Info: // First Name // Last Name //TotalPaid //Quantity //QuantityName var firstName = transaction.TransactionAnswers.Where(a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_FirstName).FirstOrDefault().Answer ?? string.Empty; var lastName = transaction.TransactionAnswers.Where(a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_LastName).FirstOrDefault().Answer ?? string.Empty; var totalPaid = transaction.TotalPaid.ToString("C"); var quantity = transaction.Quantity.ToString(); var quantityName = string.Empty; if (transaction.Item != null) { quantityName = transaction.Item.QuantityName ?? string.Empty; } var paymentLog = transaction.PaymentLogs.Where(a => a.Accepted).FirstOrDefault(); var paymentMethod = string.Empty; if(paymentLog != null) { if(paymentLog.Check) { paymentMethod = "Check"; } if (paymentLog.Credit) { paymentMethod = "Credit Card"; } } var donationThanks = string.Empty; if (transaction.DonationTotal > 0 && transaction.Paid) { donationThanks = string.Format(ScreenText.STR_DonationText, transaction.DonationTotal.ToString("C")); } body = body.Replace("{FirstName}", firstName); body = body.Replace("{LastName}", lastName); body = body.Replace("{TotalPaid}", totalPaid); body = body.Replace("{Quantity}", quantity); body = body.Replace("{QuantityName}", quantityName); body = body.Replace("{TransactionNumber}", transaction.TransactionNumber); body = body.Replace("{PaymentMethod}", paymentMethod); body = body.Replace("{DonationThanks}", donationThanks); /* Thank you {FirstName} {LastName} for your payment of {TotalPaid}. {DonationThanks} Your payment by {PaymentMethod} has been accepted. You have purchased {Quantity} {QuantityName}. Your Transaction number is: {TransactionNumber} */ //MailMessage message = new MailMessage("*****@*****.**", emailAddress, // "payment confirmed", // "your payment of " + transaction.TotalPaid.ToString("C") + // " has been accepted."); MailMessage message = new MailMessage("*****@*****.**", emailAddress, subject, body); message.IsBodyHtml = true; try { _emailService.SendEmail(message); transaction.Notified = true; transaction.NotifiedDate = SystemTime.Now(); repository.OfType<Transaction>().EnsurePersistent(transaction); } catch (Exception) { } }
public void SendRefundNotification(User user, Transaction refundTransaction, bool canceled) { var email = CloudConfigurationManager.GetSetting("EmailForRefunds"); if(string.IsNullOrWhiteSpace(email)) { email = "*****@*****.**"; } var message = new MailMessage("*****@*****.**", email) { IsBodyHtml = true }; if(canceled) { message.Subject = "Registration Refund CANCELED"; } else { message.Subject = "Registration Refund"; } var fid = string.Empty; if (refundTransaction.ParentTransaction.FidUsed != null) { fid = refundTransaction.ParentTransaction.FidUsed; } else { fid = refundTransaction.ParentTransaction.Item.TouchnetFID ?? string.Empty; } var body = new StringBuilder("Refund Information<br/><br/>"); body.Append("<b>Refunder</b><br/>"); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Name", user.FullName)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Email", user.Email)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Kerb", user.LoginID)); body.Append("<br/>"); body.Append("<b>Details</b><br/>"); body.Append(string.Format(" <b>{0} :</b> {1} FID={2}<br/>", "Touchnet Id", refundTransaction.ParentTransaction.TransactionGuid, fid)); body.Append(string.Format(" <b>{0} :</b> ${1}<br/>", "Refund Amount", refundTransaction.Amount)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Date", refundTransaction.TransactionDate)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Event Name", refundTransaction.Item.Name)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Event Id", refundTransaction.Item.Id)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Transaction", refundTransaction.ParentTransaction.TransactionNumber)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Reason For Refund", refundTransaction.CorrectionReason)); try { var contactFirstName = refundTransaction.ParentTransaction.TransactionAnswers.FirstOrDefault(a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_FirstName).Answer; var contactLastName = refundTransaction.ParentTransaction.TransactionAnswers.FirstOrDefault(a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_LastName).Answer; var contactEmail = refundTransaction.ParentTransaction.TransactionAnswers.FirstOrDefault(a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_Email).Answer; body.Append("<br/>"); body.Append("<b>Billing Contact</b><br/>"); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "First Name", contactFirstName)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Last Name", contactLastName)); body.Append(string.Format(" <b>{0} :</b> {1}<br/>", "Email", contactEmail)); } catch(Exception ex) { } message.Body = body.ToString(); _emailService.SendEmail(message); }
public void TestUncorrectedDonationTotalWithNegativeDonationWillSumIt() { #region Arrange var transaction = GetValid(9); transaction.Amount = 3m; var donationTransaction = new Transaction(transaction.Item); donationTransaction.Donation = true; donationTransaction.Amount = 10.00m; var donationTransaction2 = new Transaction(transaction.Item); donationTransaction2.Donation = true; donationTransaction2.Amount = 15.00m; var donationTransaction3 = new Transaction(transaction.Item); donationTransaction3.Donation = true; donationTransaction3.Amount = 11.00m; //This one really should never happen donationTransaction3.CreatedBy = "test"; transaction.AddChildTransaction(donationTransaction); transaction.AddChildTransaction(donationTransaction2); transaction.AddChildTransaction(donationTransaction3); #endregion Arrange #region Act var result = transaction.UncorrectedDonationTotal; #endregion Act #region Assert Assert.AreEqual(36, result); #endregion Assert }
public void TestRemoveRefundInactivatesActiveRefundAndSaves() { #region Arrange Controller.ControllerContext.HttpContext.Response .Expect(a => a.ApplyAppPathModifier(null)).IgnoreArguments() .Return("http://sample.com/ItemManagement/Details/2").Repeat.Any(); Controller.Url = MockRepository.GenerateStub<UrlHelper>(Controller.ControllerContext.RequestContext); Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { RoleNames.Refunder, RoleNames.Admin }); ControllerRecordFakes.FakeItems(Items, 2); ControllerRecordFakes.FakeUsers(Users, 3); ControllerRecordFakes.FakeEditors(Editors, 3); Users[0].LoginID = "UserName"; for (int i = 0; i < 3; i++) { Editors[i].User = Users[i]; } Items[0].AddEditor(Editors[1]); Items[0].AddEditor(Editors[2]); Items[1].AddEditor(Editors[0]); Items[1].AddEditor(Editors[1]); Items[1].AddEditor(Editors[2]); var transactions = new List<Transaction>(2); transactions.Add(CreateValidEntities.Transaction(1)); transactions.Add(CreateValidEntities.Transaction(2)); transactions[0].Item = Items[0]; transactions[1].Item = Items[1]; var refund = new Transaction(Items[0]); refund.Refunded = true; refund.Amount = 0.01m; refund.IsActive = true; transactions[0].AddChildTransaction(refund); ControllerRecordFakes.FakeTransaction(1, TransactionRepository, transactions); #endregion Arrange #region Act var result = Controller.RemoveRefund(1, "", "") .AssertHttpRedirect(); #endregion Act #region Assert Assert.IsNull(Controller.Message); Assert.AreEqual("http://sample.com/ItemManagement/Details/2?Refunds-orderBy=&Refunds-page=1#Refunds", result.Url); TransactionRepository.AssertWasCalled(a => a.EnsurePersistent(Arg<Transaction>.Is.Anything)); var args = (Transaction)TransactionRepository.GetArgumentsForCallsMadeOn(a => a.EnsurePersistent(Arg<Transaction>.Is.Anything))[0][0]; Assert.IsNotNull(args); Assert.AreEqual(1, args.ChildTransactions.Count()); Assert.IsFalse(args.RefundIssued); Assert.AreEqual(0m, args.RefundAmount); Assert.IsFalse(args.ChildTransactions.ElementAt(0).IsActive); #endregion Assert }
public void TestRefundGetReturnsViewWhenNoActiveRefundExists() { #region Arrange Controller.ControllerContext.HttpContext.Response .Expect(a => a.ApplyAppPathModifier(null)).IgnoreArguments() .Return("http://sample.com/ItemManagement/Details/2").Repeat.Any(); Controller.Url = MockRepository.GenerateStub<UrlHelper>(Controller.ControllerContext.RequestContext); Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { RoleNames.Refunder, RoleNames.Admin }); ControllerRecordFakes.FakeItems(Items, 2); ControllerRecordFakes.FakeUsers(Users, 3); ControllerRecordFakes.FakeEditors(Editors, 3); Users[0].LoginID = "UserName"; for (int i = 0; i < 3; i++) { Editors[i].User = Users[i]; } Items[0].AddEditor(Editors[1]); Items[0].AddEditor(Editors[2]); //Items[1].AddEditor(Editors[0]); //Try using admin above. Items[1].AddEditor(Editors[1]); Items[1].AddEditor(Editors[2]); var transactions = new List<Transaction>(2); transactions.Add(CreateValidEntities.Transaction(1)); transactions.Add(CreateValidEntities.Transaction(2)); transactions[0].Item = Items[0]; transactions[1].Item = Items[1]; var refund = new Transaction(Items[1]); refund.Refunded = true; refund.Amount = 0.01m; refund.IsActive = false; transactions[1].AddChildTransaction(refund); SetupDataForPopulateItemTransactionAnswer(); LoadTransactionAnswers(transactions[1], QuestionSets[0], OpenIdUsers[1]); ControllerRecordFakes.FakeTransaction(1, TransactionRepository, transactions); #endregion Arrange #region Act var result = Controller.Refund(2, "", "") .AssertViewRendered() .WithViewData<EditTransactionViewModel>(); #endregion Act #region Assert Assert.IsNull(Controller.Message); TransactionRepository.AssertWasNotCalled(a => a.EnsurePersistent(Arg<Transaction>.Is.Anything)); Assert.AreEqual(" FID=001", result.Fid); #endregion Assert }
public void TestRefundGetRedirectsToUrlIfRefundAlreadyExists2() { #region Arrange Controller.ControllerContext.HttpContext.Response .Expect(a => a.ApplyAppPathModifier(null)).IgnoreArguments() .Return("http://sample.com/ItemManagement/Details/2").Repeat.Any(); Controller.Url = MockRepository.GenerateStub<UrlHelper>(Controller.ControllerContext.RequestContext); Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { RoleNames.Refunder, RoleNames.Admin }); ControllerRecordFakes.FakeItems(Items, 2); ControllerRecordFakes.FakeUsers(Users, 3); ControllerRecordFakes.FakeEditors(Editors, 3); Users[0].LoginID = "UserName"; for (int i = 0; i < 3; i++) { Editors[i].User = Users[i]; } Items[0].AddEditor(Editors[1]); Items[0].AddEditor(Editors[2]); //Items[1].AddEditor(Editors[0]); //Try using admin above. Items[1].AddEditor(Editors[1]); Items[1].AddEditor(Editors[2]); var transactions = new List<Transaction>(2); transactions.Add(CreateValidEntities.Transaction(1)); transactions.Add(CreateValidEntities.Transaction(2)); transactions[0].Item = Items[0]; transactions[1].Item = Items[1]; var refund = new Transaction(Items[1]); refund.Refunded = true; refund.Amount = 0.01m; transactions[1].AddChildTransaction(refund); ControllerRecordFakes.FakeTransaction(1, TransactionRepository, transactions); #endregion Arrange #region Act var result = Controller.Refund(2, "", "") .AssertHttpRedirect(); #endregion Act #region Assert Assert.AreEqual("http://sample.com/ItemManagement/Details/2?Refunds-orderBy=&Refunds-page=1#Refunds", result.Url); Assert.AreEqual("Active Refund already exists.", Controller.Message); TransactionRepository.AssertWasNotCalled(a => a.EnsurePersistent(Arg<Transaction>.Is.Anything)); #endregion Assert }
public void TestDetailsRefundReturnsExpectedViewData() { #region Arrange Controller.ControllerContext.HttpContext.Response .Expect(a => a.ApplyAppPathModifier(null)).IgnoreArguments() .Return("http://sample.com/ItemManagement/Details/2").Repeat.Any(); Controller.Url = MockRepository.GenerateStub<UrlHelper>(Controller.ControllerContext.RequestContext); Controller.ControllerContext.HttpContext = new MockHttpContext(1, new[] { RoleNames.Refunder, RoleNames.Admin }); ControllerRecordFakes.FakeItems(Items, 2); ControllerRecordFakes.FakeUsers(Users, 3); ControllerRecordFakes.FakeEditors(Editors, 3); Users[0].LoginID = "UserName"; for (int i = 0; i < 3; i++) { Editors[i].User = Users[i]; } Items[0].AddEditor(Editors[1]); Items[0].AddEditor(Editors[2]); Items[1].AddEditor(Editors[0]); Items[1].AddEditor(Editors[1]); Items[1].AddEditor(Editors[2]); var transactions = new List<Transaction>(2); transactions.Add(CreateValidEntities.Transaction(1)); transactions.Add(CreateValidEntities.Transaction(2)); transactions[0].Item = Items[0]; transactions[1].Item = Items[1]; var refund = new Transaction(Items[0]); refund.Refunded = true; refund.Amount = 0.01m; refund.IsActive = true; refund.CorrectionReason = "Detail reason here"; refund.CreatedBy = "NotMe"; transactions[0].AddChildTransaction(refund); transactions[0].Amount = 20m; SetupDataForPopulateItemTransactionAnswer(); LoadTransactionAnswers(transactions[0], QuestionSets[0], OpenIdUsers[1]); ControllerRecordFakes.FakeTransaction(1, TransactionRepository, transactions); #endregion Arrange #region Act var result = Controller.DetailsRefund(1, "", "") .AssertViewRendered() .WithViewData<EditTransactionViewModel>(); #endregion Act #region Assert Assert.IsNull(Controller.Message); Assert.AreEqual(0.01m, result.RefundAmount); Assert.AreEqual("*****@*****.**", result.ContactEmail); Assert.AreEqual("FirstName LastName", result.ContactName); Assert.AreEqual("Detail reason here", result.CorrectionReason); Assert.AreEqual("NotMe", result.CreatedBy); Assert.AreEqual(" FID=001", result.Fid); #endregion Assert }
public ActionResult Edit(Transaction transaction, string checkSort, string checkPage) { ModelState.Clear(); var transactionToUpdate = Repository.OfType<Transaction>().GetNullableById(transaction.Id); if (transactionToUpdate == null) { Message = NotificationMessages.STR_ObjectNotFound.Replace(NotificationMessages.ObjectType, "Transaction"); return this.RedirectToAction<ItemManagementController>(a => a.List(null)); } if (transactionToUpdate.Item == null || !Access.HasItemAccess(CurrentUser, transactionToUpdate.Item)) { if (transactionToUpdate.Item == null) { Message = NotificationMessages.STR_ObjectNotFound.Replace(NotificationMessages.ObjectType, "Item"); } else { Message = NotificationMessages.STR_NoEditorRights.Replace(NotificationMessages.ObjectType, "Item"); } return this.RedirectToAction<ItemManagementController>(a => a.List(null)); } var pageAndSort = ValidateParameters.PageAndSort("ItemDetails", checkSort, checkPage); var correctionTransaction = new Transaction(transactionToUpdate.Item); correctionTransaction.Amount = transaction.Amount; correctionTransaction.CorrectionReason = transaction.CorrectionReason; if (correctionTransaction.Amount > 0) { correctionTransaction.Donation = true; } else { correctionTransaction.Donation = false; } correctionTransaction.CreatedBy = CurrentUser.Identity.Name; transactionToUpdate.AddChildTransaction(correctionTransaction); //There is a similar check in the payment controller, but with a different message if (transactionToUpdate.TotalPaid > transactionToUpdate.Total) { ModelState.AddModelError("Corrections", "The total of all correction amounts must not exceed the amount already paid."); } correctionTransaction.TransferValidationMessagesTo(ModelState);//Validate Child as well as parent(next Line) transactionToUpdate.TransferValidationMessagesTo(ModelState); if (ModelState.IsValid) { Repository.OfType<Transaction>().EnsurePersistent(transactionToUpdate); //return this.RedirectToAction<ItemManagementController>(a => a.Details(transactionToUpdate.Item.Id)); return Redirect(Url.DetailItemUrl ( transactionToUpdate.Item.Id, StaticValues.Tab_Checks, pageAndSort["sort"], pageAndSort["page"]) ); } //TODO: We could replace the line below with a rollback to be more consistent. transactionToUpdate.ChildTransactions.Remove(correctionTransaction); var viewModel = EditTransactionViewModel.Create(Repository, transactionToUpdate); viewModel.TransactionValue = transactionToUpdate; viewModel.ContactName = transactionToUpdate.TransactionAnswers.Where( a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_FirstName).FirstOrDefault().Answer; viewModel.ContactName = viewModel.ContactName + " " + transactionToUpdate.TransactionAnswers.Where( a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_LastName).FirstOrDefault().Answer; viewModel.ContactEmail = transactionToUpdate.TransactionAnswers.Where( a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_Email).FirstOrDefault().Answer; viewModel.Sort = pageAndSort["sort"]; viewModel.Page = pageAndSort["page"]; return View(viewModel); }
public ActionResult Checkout(int id, string referenceIdHidden, int quantity, decimal? donation, decimal? displayAmount, string paymentType, string restrictedKey, string coupon, QuestionAnswerParameter[] transactionAnswers, QuestionAnswerParameter[] quantityAnswers, bool captchaValid) { // if the arrays are null create new blank ones if (transactionAnswers==null) transactionAnswers = new QuestionAnswerParameter[0]; if (quantityAnswers==null) quantityAnswers = new QuestionAnswerParameter[0]; #region DB Queries // get the item var item = Repository.OfType<Item>().GetNullableById(id); // get all the questions in 1 queries var questionIds = transactionAnswers.Select(b => b.QuestionId).ToList().Union(quantityAnswers.Select(c => c.QuestionId).ToList()).ToArray(); var allQuestions = Repository.OfType<Question>().Queryable.Where(a => questionIds.Contains(a.Id)).ToList(); if(!string.IsNullOrWhiteSpace(referenceIdHidden)) { var refId = allQuestions.FirstOrDefault(a => a.Name == "Reference Id"); if(refId != null) { if(transactionAnswers.Any(a => a.QuestionId == refId.Id && string.IsNullOrWhiteSpace(a.Answer))) { transactionAnswers.First(a => a.QuestionId == refId.Id && string.IsNullOrWhiteSpace(a.Answer)).Answer = referenceIdHidden; } } } // get the coupon var coup = Repository.OfType<Coupon>().Queryable.Where(a => a.Code == coupon && a.Item == item && a.IsActive).FirstOrDefault(); #endregion // invalid item, or not available for registration if (item == null) { Message = NotificationMessages.STR_ObjectNotFound.Replace(NotificationMessages.ObjectType, "Item"); return this.RedirectToAction<HomeController>(a => a.Index()); } if (!Access.HasItemAccess(CurrentUser, item)) //Allow editors to over ride and register for things { if (!item.IsAvailableForReg) { Message = NotificationMessages.STR_NotAvailable.Replace(NotificationMessages.ObjectType, "Item"); return this.RedirectToAction<HomeController>(a => a.Index()); } } if (!captchaValid) { ModelState.AddModelError("Captcha", "Captcha values are not valid."); } if(quantity < 1 ) { ModelState.AddModelError("Quantity", "Quantity must be at least 1"); } var transaction = new Transaction(item); var questionCount = 0; foreach (var itemQuestionSet in item.QuestionSets.Where(a => a.QuantityLevel)) { questionCount += itemQuestionSet.QuestionSet.Questions.Count; } if (questionCount * quantity != quantityAnswers.Count()) { ModelState.AddModelError("Quantity Level", "The number of answers does not match the number of Quantity Level questions."); } // fill the openid user if they are openid validated if (HttpContext.Request.IsOpenId()) { // doesn't matter if it's null, just assign what we have transaction.OpenIDUser = _openIdUserRepository.GetNullableById(CurrentUser.Identity.Name); } // deal with selected payment type if (paymentType == StaticValues.CreditCard) { transaction.Credit = true; transaction.Check = false; } else if (paymentType == StaticValues.Check) { transaction.Check = true; transaction.Credit = false; } // deal with the amount var amount = item.CostPerItem*quantity; // get the initial amount decimal discount = 0.0m; // used to calculate total discount decimal couponAmount = 0.0m; // used to display individual discount of one coupon // get the email if (coup != null) { // calculate the coupon discount var emailQ = allQuestions.Where(a => a.Name == StaticValues.Question_Email && a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation).FirstOrDefault(); if (emailQ != null) { // get the answer var answer = transactionAnswers.Where(a => a.QuestionId == emailQ.Id).FirstOrDefault(); discount = coup.UseCoupon(answer != null ? answer.Answer : null, quantity); } else { discount = coup.UseCoupon(null, quantity); } // if coupon is used set display value if(discount == 0) { ModelState.AddModelError("Coupon", NotificationMessages.STR_Coupon_could_not_be_used); transaction.Coupon = null; } else { couponAmount = coup.DiscountAmount; // record the coupon usage to this transaction transaction.Coupon = coup; } } transaction.Amount = amount - discount; transaction.Quantity = quantity; // deal with the transaction answers foreach (var qa in transactionAnswers) { var question = allQuestions.Where(a => a.Id == qa.QuestionId).FirstOrDefault(); // if question is null just drop it if (question != null) { //var answer = question.QuestionType.Name != QuestionTypeText.STR_CheckboxList // ? qa.Answer // : (qa.CblAnswer != null ? string.Join(", ", qa.CblAnswer) : string.Empty); var answer = CleanUpAnswer(question.QuestionType.Name, qa, question.ValidationClasses); // validate each of the validators foreach (var validator in question.Validators) { string message; if (!Validate(validator, answer, question.Name, out message)) { ModelState.AddModelError("Transaction Question", message); } } var qanswer = new TransactionAnswer(transaction, question.QuestionSet, question, answer); transaction.AddTransactionAnswer(qanswer); } //TODO: consider writing this to a log or something } // deal with quantity level answers for (var i = 0; i < quantity; i++) { // generate the unique id for each quantity var quantityId = Guid.NewGuid(); foreach (var qa in quantityAnswers.Where(a => a.QuantityIndex == i)) { var question = allQuestions.Where(a => a.Id == qa.QuestionId).FirstOrDefault(); // if question is null just drop it if (question != null) { //var answer = question.QuestionType.Name != QuestionTypeText.STR_CheckboxList // ? qa.Answer // : (qa.CblAnswer != null ? string.Join(", ", qa.CblAnswer) : string.Empty); var answer = CleanUpAnswer(question.QuestionType.Name, qa, question.ValidationClasses); var fieldName = string.Format("The answer for question \"{0}\" for {1} {2}", question.Name, item.QuantityName, (i + 1)); // validate each of the validators foreach (var validator in question.Validators) { string message; if (!Validate(validator, answer, fieldName, out message)) { ModelState.AddModelError("Quantity Question", message); } } var qanswer = new QuantityAnswer(transaction, question.QuestionSet, question, answer, quantityId); transaction.AddQuantityAnswer(qanswer); } } } // deal with donation if (donation.HasValue && donation.Value > 0.0m) { var donationTransaction = new Transaction(item); donationTransaction.Donation = true; donationTransaction.Amount = donation.Value; transaction.AddChildTransaction(donationTransaction); } // check to see if it's a restricted item if (!string.IsNullOrEmpty(item.RestrictedKey) && item.RestrictedKey != restrictedKey) { ModelState.AddModelError("Restricted Key", "The item is restricted please enter the passphrase."); } if (!Access.HasItemAccess(CurrentUser, item)) //Allow editors to over ride and register for things { // do a final check to make sure the inventory is there if (item.Sold + quantity > item.Quantity) { ModelState.AddModelError("Quantity", "There is not enough inventory to complete your order."); } } //if (transaction.Total == 0 && transaction.Credit) //{ // ModelState.AddModelError("Payment Method", "Please select check payment type when amount is zero."); //} if(transaction.Total == 0) { transaction.Credit = false; transaction.Check = true; } if (transaction.Total != displayAmount) { ModelState.AddModelError("Total", "We are sorry, the total amount displayed on the form did not match the total we calculated."); } MvcValidationAdapter.TransferValidationMessagesTo(ModelState, transaction.ValidationResults()); if (ModelState.IsValid) { // create the new transaction Repository.OfType<Transaction>().EnsurePersistent(transaction); if(transaction.Paid && transaction.Check) { if(transaction.Item.CostPerItem == 0.0m || couponAmount > 0.0m) { //Ok, it is paid because the amount is zero, and it is because a coupon was used or the cost was zero try { //If the tranascation is not evicted, it doesn't refresh from the database and the transaction number is null. var saveId = transaction.Id; NHibernateSessionManager.Instance.GetSession().Evict(transaction); transaction = Repository.OfType<Transaction>().GetNullableById(saveId); // attempt to get the contact information question set and retrieve email address var question = transaction.TransactionAnswers.Where(a => a.QuestionSet.Name == StaticValues.QuestionSet_ContactInformation && a.Question.Name == StaticValues.Question_Email).FirstOrDefault(); if (question != null) { // send an email to the user _notificationProvider.SendConfirmation(Repository, transaction, question.Answer); } } catch (Exception) { } } } var updatedItem = Repository.OfType<Item>().GetNullableById(transaction.Item.Id); if (updatedItem != null) { //For whatever reason, if you are logged in with your CAES user, the item is updated, //if you are logged in with open id (google), item is not updated. var transactionQuantity = transaction.Quantity; if (updatedItem.Transactions.Contains(transaction)) { transactionQuantity = 0; } if (updatedItem.Quantity - (updatedItem.Sold + transactionQuantity) <= 10) { _notificationProvider.SendLowQuantityWarning(Repository, updatedItem, transactionQuantity); } } // redirect to confirmation and let the user decide payment or not return this.RedirectToAction(a => a.Confirmation(transaction.Id)); } var viewModel = ItemDetailViewModel.Create(Repository, _openIdUserRepository, item, CurrentUser.Identity.Name, referenceIdHidden, null, null); viewModel.Quantity = quantity; viewModel.Answers = PopulateItemTransactionAnswer(transactionAnswers, quantityAnswers); viewModel.CreditPayment = (paymentType == StaticValues.CreditCard); viewModel.CheckPayment = (paymentType == StaticValues.Check); viewModel.TotalAmountToRedisplay = transaction.Total; viewModel.CouponAmountToDisplay = couponAmount; viewModel.CouponTotalDiscountToDisplay = discount; return View(viewModel); }