public RewardsAccount CalculatePointsAccount(IList <Product> products) { var appliedAmount = 0M; if (IsRewardPointsAccount) { var pointAccountResponse = Exigo.GetCustomerPointAccount(CustomerId, RewardPointsAccountId.Value); var creditsRemaining = (null != pointAccountResponse ? pointAccountResponse.Balance : 0M); var productWithDiscount = GetRewardProducts(products); foreach (var product in productWithDiscount) { if (product.Quantity < product.Discounts.Count) { throw new ApplicationException("Number of discounts applied cannot exceed the number of products."); } appliedAmount += product.Discounts.Where(discount => discount.DiscountType == DiscountType.RecruitingReward).Sum(discount => discount.AppliedAmount); } RewardsAccount account = new RewardsAccount { PointAccountID = RewardPointsAccountId.Value, Balance = creditsRemaining, AppliedAmount = appliedAmount }; return(account); } return(null); }
public virtual bool AllowAddToCart(Item rewardProduct, List <IShoppingCartItem> productsInShoppingCart) { var rewardProducts = GetRewardProducts(productsInShoppingCart); if (rewardProducts.Select(p => p.ItemCode).Contains(rewardProduct.ItemCode)) { // The same product cannot be added to the cart multiple times with this reward applied return(false); } if (IsRewardPointsAccount) { RewardsAccount rewardsAccount = CalculatePointsAccount(productsInShoppingCart); if (rewardsAccount.AmountRemaining <= 0) { // A credit must be available to apply a reward to a another product return(false); } } List <string> alreadyPurchasedItemCodes = PurchasedItemCodes(); alreadyPurchasedItemCodes.AddRange(productsInShoppingCart.Select(i => i.ItemCode).ToList()); if (alreadyPurchasedItemCodes.Contains(rewardProduct.ItemCode)) { // This product has already been purchased in a previuos order return(false); } return(true); }
public PremiumTier( int pointsBalance, RewardsAccount account, ISendsEmails emailer) : base(emailer) { PointBalance = pointsBalance; Account = account; Initialize(); }
/// <summary> /// This method verifies an order is valid to be submitted in regards to the reward. An exception is thrown if the order is invalid. /// </summary> public void VerifyOrderIsValid(IOrder order) { IList <Product> rewardProducts = GetRewardProducts(order.Products); if (rewardProducts.Count() > 0) { if (CustomerId == 0) { throw new ApplicationException("CustomerId cannot be zero"); } // All products must be eligible for half off IEnumerable <Product> productsNotEligibleHalfOff = rewardProducts.Where(p => !p.HalfOffRewardsCreditsEligible); if (productsNotEligibleHalfOff.Count() > 0) { throw new ApplicationException(string.Format("{0} is not not eligible for half off credit", productsNotEligibleHalfOff.First().Description)); } // Quantities greater than one cannot be purchased using the reward IEnumerable <Product> productsWithMultipleRewards = rewardProducts.Where(p => p.Discounts.Where(d => d.DiscountType == RewardHalfOffDiscountType).Count() > 1); if (productsWithMultipleRewards.Count() > 1) { throw new ApplicationException("Half Off Discount cannot be applied multiple times to the same product."); } if (IsRewardPointsAccount) { // Credits cannot be exceeded (one credit per product purchased with this reward) RewardsAccount rewardsAccount = CalculatePointsAccount(order.Products); if (rewardsAccount.AmountRemaining < 0) { throw new ApplicationException("You've exceeded your rewards balance"); } } // Product could not have been purchased before using this reward var previouslyPurchasedItemCodes = PurchasedItemCodes(); IEnumerable <Product> alreadyPurchasedProducts = order.Products.Where(p => previouslyPurchasedItemCodes.Contains(p.ItemCode)); if (alreadyPurchasedProducts.Count() > 0) { throw new ApplicationException(string.Format("{0} has already been purchased with this reward", alreadyPurchasedProducts.First().Description)); } } }
/// <summary> /// This method calculates the points account for this reward. /// </summary> public RewardsAccount CalculatePointsAccount(IList <Product> productsInShoppingCart) { if (IsRewardPointsAccount) { var pointAccountResponse = Exigo.GetCustomerPointAccount(CustomerId, RewardPointsAccountId.Value); var creditsRemaining = (null != pointAccountResponse ? pointAccountResponse.Balance : 0M); var productWithDiscount = GetRewardProducts(productsInShoppingCart); var account = new RewardsAccount { PointAccountID = RewardPointsAccountId.Value, Balance = creditsRemaining, AppliedAmount = productWithDiscount.Count() }; return(account); } return(null); }
static void Main() { var logger = new ConsoleLogger(); var emailer = new Emailer(logger); logger.LogInfo("☕ Welcome to the Cafe Rewards Program"); logger.LogInfo("--------------------------------------"); // Sign up for the Rewards Program var rewards = new RewardsAccount(logger, emailer, "Katrina"); logger.LogInfo("Simulating Customer Activity"); logger.LogInfo("--------------------------------------"); // Simulate Customer Activity rewards.OnPurchase(1); rewards.OnPurchase(1); rewards.OnPurchase(1); rewards.OnPurchase(1); rewards.UsePoints(2); rewards.UsePoints(1); }
// TODO: This method can replace the other AddToCart method once it's implemented. protected ActionResult AddToCart(Product product, Discount discount = null, IIndividualReward reward = null, Event @event = null) { var shoppingCart = GetShoppingCart(); try { while (product.Discounts.Any()) { product.UnapplyDiscount(product.Discounts.First()); } // Add the product to the order. var p = product.AddToOrder(shoppingCart); RewardsAccount pointAccount = null; // Validate that the discount can be applied // to the product using our validator. if (null != discount) { bool eventAllowsDiscount = shoppingCart.ShopperIsHost || shoppingCart.ShopperIsEventSa; // || shoppingCart.ShopperIsBookingRewardsOwner; bool rewardAllowsDiscount = reward != null && reward.IsRewardDiscount(discount) && reward.AllowAddToCart(product, shoppingCart.Products); if ((eventAllowsDiscount || rewardAllowsDiscount) && DiscountValidator.IsValidFor(discount, p, @event)) { // TODO: Need to find a better way to map discounts and which point accounts // are deducted based on the discount. switch (discount.DiscountType) { case DiscountType.RewardsCash: pointAccount = shoppingCart.GetRewardsAccount(PointAccounts.HostRewardsCash); discount.DiscountAmount = pointAccount.AmountRemaining; break; case DiscountType.RecruitingReward: pointAccount = shoppingCart.GetRewardsAccount(PointAccounts.RecruitingRewards); discount.DiscountAmount = pointAccount.AmountRemaining; break; case DiscountType.EnrolleeReward: pointAccount = shoppingCart.GetRewardsAccount(PointAccounts.EnrolleeRewards); discount.DiscountAmount = pointAccount.AmountRemaining; break; case DiscountType.HalfOffCredits: pointAccount = shoppingCart.GetRewardsAccount(PointAccounts.Host12offcredits); break; //case DiscountType.BookingRewards: // pointAccount = shoppingCart.GetRewardsAccount(PointAccounts.BookingsRewardsCash); // discount.DiscountAmount = pointAccount.AmountRemaining; // break; case DiscountType.HostSpecial: // TODO: Look into why DI is broken on AJAX calls, seemingly. var hostSpecialReward = new RewardService().GetHostSpecialReward(shoppingCart.EventId.Value); // TODO: Need to validate that the discount exceeds the sales threshold in an IDiscountValidator discount.DiscountAmount = hostSpecialReward.DiscountAmount; break; case DiscountType.Unknown: break; case DiscountType.Fixed: break; case DiscountType.Percent: break; case DiscountType.EBRewards: break; case DiscountType.SAHalfOff: break; case DiscountType.SAHalfOffOngoing: break; case DiscountType.NewProductsLaunchReward: break; case DiscountType.RetailPromoFixed: break; case DiscountType.RetailPromoPercent: break; case DiscountType.PromoCode: break; default: throw new ArgumentOutOfRangeException(); } if ((pointAccount == null && discount.DiscountAmount > 0M) || (pointAccount != null && pointAccount.AmountRemaining > 0M)) { p.ApplyDiscount(discount); } else { // TODO: Need implement error handling at the client for JSON response //ModelState.AddModelError("RewardsError", "The applied rewards amount exceeds the current balance."); } } } return(new JsonNetResult(new { status = 200, cart = shoppingCart })); } catch (Exception) { return(new JsonNetResult(new { status = 500, cart = shoppingCart })); } }