private Cart GetCart(string cartId, CommerceContext commerceContext, string baseUrl)
        {
            var shopName    = commerceContext.CurrentShopName();
            var shopperId   = commerceContext.CurrentShopperId();
            var customerId  = commerceContext.CurrentCustomerId();
            var environment = commerceContext.Environment.Name;

            var url = string.Format(Constants.Settings.EndpointUrl, baseUrl, cartId);

            var client = new HttpClient();

            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(Constants.Settings.AppJson));
            client.DefaultRequestHeaders.Add(Constants.Settings.ShopName, shopName);
            client.DefaultRequestHeaders.Add(Constants.Settings.ShopperId, shopperId);
            client.DefaultRequestHeaders.Add(Constants.Settings.Language, "en-US");
            client.DefaultRequestHeaders.Add(Constants.Settings.Environment, environment);
            client.DefaultRequestHeaders.Add(Constants.Settings.CustomerId, customerId);
            client.DefaultRequestHeaders.Add(Constants.Settings.Currency, commerceContext.CurrentCurrency());
            client.DefaultRequestHeaders.Add(Constants.Settings.Roles, Constants.Settings.CartRoles);


            try
            {
                var cart = new Cart();

                var response = client.GetAsync(url).Result;

                if (response != null)
                {
                    var task = response.Content.ReadAsStreamAsync().ContinueWith(t =>
                    {
                        var stream = t.Result;
                        using (var reader = new StreamReader(stream))
                        {
                            var responseValue = reader.ReadToEnd();
                            cart = JsonConvert.DeserializeObject <Cart>(responseValue);
                        }
                    });

                    task.Wait();
                }

                client.Dispose();
                return(cart);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                client.Dispose();
                return(null);
            }
        }
Example #2
0
        public static CartLevelAwardedAdjustment CreateCartLevelAwardedAdjustment(decimal amountOff, string awardingBlock,
                                                                                  CommerceContext commerceContext)
        {
            var    propertiesModel = commerceContext.GetObject <PropertiesModel>();
            string discount        = commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount;

            var adjustment = new CartLevelAwardedAdjustment
            {
                Name           = propertiesModel?.GetPropertyValue("PromotionText") as string ?? discount,
                DisplayName    = propertiesModel?.GetPropertyValue("PromotionCartText") as string ?? discount,
                Adjustment     = new Money(commerceContext.CurrentCurrency(), amountOff),
                AdjustmentType = discount,
                IsTaxable      = false,
                AwardingBlock  = awardingBlock
            };

            return(adjustment);
        }
        /// <summary>
        /// The process of the command
        /// </summary>
        /// <param name="commerceContext">
        /// The commerce context
        /// </param>
        /// <param name="cartLineComponent"></param>
        /// <param name="awardingAction"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        public virtual void Process(CommerceContext commerceContext, [NotNull] CartLineComponent cartLineComponent, [NotNull] string awardingAction)
        {
            using (CommandActivity.Start(commerceContext, this))
            {
                var discountAdjustmentType = commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount;
                var propertiesModel        = commerceContext.GetObject <PropertiesModel>();
                var totals         = commerceContext?.GetObject <CartTotals>();
                var discountAmount = cartLineComponent.UnitListPrice.Amount * decimal.MinusOne;

                cartLineComponent.Adjustments.Add(new CartLineLevelAwardedAdjustment
                {
                    Name           = (propertiesModel?.GetPropertyValue("PromotionText") as string ?? discountAdjustmentType),
                    DisplayName    = (propertiesModel?.GetPropertyValue("PromotionCartText") as string ?? discountAdjustmentType),
                    Adjustment     = new Money(commerceContext.CurrentCurrency(), discountAmount),
                    AdjustmentType = discountAdjustmentType,
                    IsTaxable      = false,
                    AwardingBlock  = propertiesModel?.GetPropertyValue("PromotionId") as string
                });

                totals.Lines[cartLineComponent.Id].SubTotal.Amount = totals.Lines[cartLineComponent.Id].SubTotal.Amount + discountAmount;
                cartLineComponent.GetComponent <MessagesComponent>().AddMessage(commerceContext.GetPolicy <KnownMessageCodePolicy>().Promotions, string.Format("PromotionApplied: {0}", propertiesModel?.GetPropertyValue("PromotionId") ?? awardingAction));
            }
        }
Example #4
0
            public void Execute_WithProperties(
                BaseCartItemSubtotalAmountOffAction action,
                IRuleValue <decimal> subtotal,
                IRuleValue <decimal> amountOff,
                Cart cart,
                CommerceContext commerceContext,
                IRuleExecutionContext context)
            {
                /**********************************************
                * Arrange
                **********************************************/
                cart.Adjustments.Clear();
                cart.Lines.ForEach(l => l.Adjustments.Clear());

                var globalPricingPolicy = commerceContext.GetPolicy <GlobalPricingPolicy>();

                globalPricingPolicy.ShouldRoundPriceCalc         = false;
                cart.Lines.ForEach(l => l.Totals.SubTotal.Amount = 100);
                var cartline = cart.Lines[1];

                cartline.Totals.SubTotal.Amount = 150;
                var cartTotals = new CartTotals(cart);

                subtotal.Yield(context).ReturnsForAnyArgs(150);
                amountOff.Yield(context).ReturnsForAnyArgs(25);
                var propertiesModel = new PropertiesModel();

                propertiesModel.Properties.Add("PromotionId", "id");
                propertiesModel.Properties.Add("PromotionCartText", "carttext");
                propertiesModel.Properties.Add("PromotionText", "text");
                commerceContext.AddObject(propertiesModel);

                context.Fact <CommerceContext>().ReturnsForAnyArgs(commerceContext);
                commerceContext.AddObject(cartTotals);
                commerceContext.AddObject(cart);
                action.MatchingLines(context).ReturnsForAnyArgs(cart.Lines);
                action.SubtotalOperator = new DecimalGreaterThanEqualToOperator();
                action.Subtotal         = subtotal;
                action.AmountOff        = amountOff;

                /**********************************************
                * Act
                **********************************************/
                Action executeAction = () => action.Execute(context);

                /**********************************************
                * Assert
                **********************************************/
                executeAction.Should().NotThrow <Exception>();
                cart.Lines.SelectMany(l => l.Adjustments).Should().HaveCount(1);
                cart.Adjustments.Should().BeEmpty();
                cartTotals.Lines[cartline.Id].SubTotal.Amount.Should().Be(125);
                cartline.Adjustments.Should().NotBeEmpty();
                cartline.Adjustments.FirstOrDefault().Should().NotBeNull();
                cartline.Adjustments.FirstOrDefault().Should().BeOfType <CartLineLevelAwardedAdjustment>();
                cartline.Adjustments.FirstOrDefault()?.Name.Should().Be("text");
                cartline.Adjustments.FirstOrDefault()?.DisplayName.Should().Be("carttext");
                cartline.Adjustments.FirstOrDefault()?.AdjustmentType.Should().Be(commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount);
                cartline.Adjustments.FirstOrDefault()?.AwardingBlock.Should().Contain(nameof(BaseCartItemSubtotalAmountOffAction));
                cartline.Adjustments.FirstOrDefault()?.IsTaxable.Should().BeFalse();
                cartline.Adjustments.FirstOrDefault()?.Adjustment.CurrencyCode.Should().Be(commerceContext.CurrentCurrency());
                cartline.Adjustments.FirstOrDefault()?.Adjustment.Amount.Should().Be(-25);
                cartline.HasComponent <MessagesComponent>().Should().BeTrue();
            }
            public void Execute_WithProperties(
                IRuleValue <string> fulfillmentOptionName,
                IRuleValue <decimal> amountOff,
                Cart cart,
                CommerceContext commerceContext,
                IRuleExecutionContext context,
                string fulfillmentOptionNameValue,
                FulfillmentComponent fulfillmentComponent)
            {
                /**********************************************
                * Arrange
                **********************************************/
                const decimal FULFILLMENT_FEE = MINIMUM_AMOUNT_OFF + 10m;

                cart.Adjustments.Clear();
                var awardedAdjustment = new AwardedAdjustment()
                {
                    Name = "FulfillmentFee"
                };

                awardedAdjustment.Adjustment = new Money(FULFILLMENT_FEE);
                cart.Adjustments.Add(awardedAdjustment);
                cart.Lines.ForEach(l => l.Adjustments.Clear());
                cart.SetComponent(fulfillmentComponent);

                context.Fact <CommerceContext>().ReturnsForAnyArgs(commerceContext);
                commerceContext.AddObject(cart);

                var globalPricingPolicy = commerceContext.GetPolicy <GlobalPricingPolicy>();

                globalPricingPolicy.ShouldRoundPriceCalc = false;
                fulfillmentOptionName.Yield(context).ReturnsForAnyArgs(fulfillmentOptionNameValue);
                amountOff.Yield(context).ReturnsForAnyArgs(MINIMUM_AMOUNT_OFF);
                var propertiesModel = new PropertiesModel();

                propertiesModel.Properties.Add("PromotionId", "id");
                propertiesModel.Properties.Add("PromotionCartText", "carttext");
                propertiesModel.Properties.Add("PromotionText", "text");
                commerceContext.AddObject(propertiesModel);

                var commander = Substitute.For <CommerceCommander>(Substitute.For <IServiceProvider>());
                var command   = Substitute.For <GetFulfillmentMethodsCommand>(
                    Substitute.For <IFindEntityPipeline>(),
                    Substitute.For <IGetCartFulfillmentMethodsPipeline>(),
                    Substitute.For <IGetCartLineFulfillmentMethodsPipeline>(),
                    Substitute.For <IGetFulfillmentMethodsPipeline>(),
                    Substitute.For <IServiceProvider>());

                var fulfillmentMethod = new FulfillmentMethod()
                {
                    FulfillmentType = fulfillmentOptionNameValue
                };

                command.Process(commerceContext).ReturnsForAnyArgs(new List <FulfillmentMethod>()
                {
                    fulfillmentMethod
                }.AsEnumerable());
                commander.When(x => x.Command <GetFulfillmentMethodsCommand>()).DoNotCallBase();
                commander.Command <GetFulfillmentMethodsCommand>().Returns(command);
                var action = new CartShippingOptionAmountOffAction(commander)
                {
                    FulfillmentOptionName = fulfillmentOptionName,
                    AmountOff             = amountOff
                };

                /**********************************************
                * Act
                **********************************************/
                Action executeAction = () => action.Execute(context);

                /**********************************************
                * Assert
                **********************************************/
                executeAction.Should().NotThrow <Exception>();
                cart.Lines.SelectMany(l => l.Adjustments).Should().HaveCount(0);
                cart.Adjustments.Should().NotBeEmpty();
                cart.Adjustments.LastOrDefault().Should().NotBeNull();
                cart.Adjustments.LastOrDefault().Should().BeOfType <CartLevelAwardedAdjustment>();
                cart.Adjustments.LastOrDefault().Name.Should().Be("text");
                cart.Adjustments.LastOrDefault().DisplayName.Should().Be("carttext");
                cart.Adjustments.LastOrDefault().AdjustmentType.Should().Be(commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount);
                cart.Adjustments.LastOrDefault().AwardingBlock.Should().Contain(nameof(CartShippingOptionAmountOffAction));
                cart.Adjustments.LastOrDefault().IsTaxable.Should().BeFalse();
                cart.Adjustments.LastOrDefault().Adjustment.CurrencyCode.Should().Be(commerceContext.CurrentCurrency());
                cart.Adjustments.LastOrDefault().Adjustment.Amount.Should().Be(-MINIMUM_AMOUNT_OFF);
                cart.HasComponent <MessagesComponent>().Should().BeTrue();
            }
        public void Execute(IRuleExecutionContext context)
        {
            CommerceContext commerceContext  = context.Fact <CommerceContext>((string)null);
            CommerceContext commerceContext1 = commerceContext;
            Cart            cart             = commerceContext1 != null?commerceContext1.GetObjects <Cart>().FirstOrDefault <Cart>() : (Cart)null;

            CommerceContext commerceContext2 = commerceContext;
            CartTotals      totals           = commerceContext2 != null?commerceContext2.GetObjects <CartTotals>().FirstOrDefault <CartTotals>() : (CartTotals)null;

            if (cart == null || !cart.Lines.Any <CartLineComponent>() || (totals == null || !totals.Lines.Any <KeyValuePair <string, Totals> >()))
            {
                return;
            }

            List <CartLineComponent> list = new List <CartLineComponent>();

            //Get the valid cartline items that matches specific tag provided
            foreach (var cartLine in cart.Lines.Where(x => x.HasComponent <CartProductComponent>()))
            {
                var firstOrDefault = cartLine.GetComponent <CartProductComponent>().Tags.FirstOrDefault(t => t.Name == this.Tag.Yield(context));
                if (!string.IsNullOrEmpty(firstOrDefault?.Name))
                {
                    list.Add(cartLine);
                }
            }
            if (!list.Any <CartLineComponent>())
            {
                return;
            }

            list.ForEach((Action <CartLineComponent>)(line =>
            {
                if (!totals.Lines.ContainsKey(line.Id))
                {
                    return;
                }
                PropertiesModel propertiesModel = commerceContext.GetObject <PropertiesModel>();
                string discountPolicy           = commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount;

                //Extract the coupon code in-order to associate coupon code with adjustment (1 to 1 mapping)
                string couponCode = string.Empty;
                if (cart.HasComponent <CartCouponsComponent>())
                {
                    if (cart.GetComponent <CartCouponsComponent>().List != null && cart.GetComponent <CartCouponsComponent>().List.Any())
                    {
                        couponCode = cart.GetComponent <CartCouponsComponent>().List.FirstOrDefault(c => c.Promotion.EntityTarget == (string)propertiesModel?.GetPropertyValue("PromotionId"))?.CouponId;
                    }
                }

                //calculate discounts on specified custom pricing
                if (line.HasComponent <CustomPriceInfoComponent>())
                {
                    var customPriceInfo = line.GetComponent <CustomPriceInfoComponent>();
                    Decimal discount    = 0;
                    if (this.BasePrice.Yield(context))
                    {
                        discount += (Decimal)((double)this.PercentOff.Yield(context) * 0.01) * (decimal.Parse(customPriceInfo.BasePrice.ToString()));
                    }
                    if (this.ActivationPrice.Yield(context))
                    {
                        discount += (Decimal)((double)this.PercentOff.Yield(context) * 0.01) * (decimal.Parse(customPriceInfo.ActivationPrice.ToString()));
                    }
                    if (this.DeliveryPrice.Yield(context))
                    {
                        discount += (Decimal)((double)this.PercentOff.Yield(context) * 0.01) * (decimal.Parse(customPriceInfo.DeliveryPrice.ToString()));
                    }
                    if (commerceContext.GetPolicy <GlobalPricingPolicy>().ShouldRoundPriceCalc)
                    {
                        discount = Decimal.Round(discount, commerceContext.GetPolicy <GlobalPricingPolicy>().RoundDigits, commerceContext.GetPolicy <GlobalPricingPolicy>().MidPointRoundUp ? MidpointRounding.AwayFromZero : MidpointRounding.ToEven);
                    }
                    Decimal amount = discount * Decimal.MinusOne;

                    //Create an adjustment and associate coupon code with coupon description delimited by '|' [Workaround for known issue with Promotion Plugin]
                    IList <AwardedAdjustment> adjustments = line.Adjustments;
                    adjustments.Add((AwardedAdjustment) new CartLineLevelAwardedAdjustment()
                    {
                        Name           = (propertiesModel?.GetPropertyValue("PromotionText") as string ?? discountPolicy),
                        DisplayName    = couponCode + "|" + (propertiesModel?.GetPropertyValue("PromotionCartText") as string ?? discountPolicy),
                        Adjustment     = new Money(commerceContext.CurrentCurrency(), amount),
                        AdjustmentType = discountPolicy,
                        IsTaxable      = false,
                        AwardingBlock  = nameof(CustomPercentOffAction)
                    });
                    totals.Lines[line.Id].SubTotal.Amount = totals.Lines[line.Id].SubTotal.Amount + amount;
                    line.GetComponent <MessagesComponent>().AddMessage(commerceContext.GetPolicy <KnownMessageCodePolicy>().Promotions, string.Format("PromotionApplied: {0}", propertiesModel?.GetPropertyValue("PromotionId") ?? (object)nameof(CustomPercentOffAction)));
                }
            }));
        }
Example #7
0
        private async Task PrettifyChild(EntityView entity, CommerceContext commerceContext)
        {
            ViewProperty originalEntity = entity.Properties.First(x =>
                                                                  x.Name.EqualsOrdinalIgnoreCase("Condition") ||
                                                                  x.Name.EqualsOrdinalIgnoreCase("Action"));

            originalEntity.IsHidden = true;

            var fullEntity = new ViewProperty
            {
                DisplayName  = originalEntity.DisplayName,
                IsHidden     = false,
                IsReadOnly   = originalEntity.IsReadOnly,
                IsRequired   = originalEntity.IsRequired,
                Name         = $"Full{originalEntity.Name}",
                OriginalType = "Html",
                Policies     = originalEntity.Policies,
                RawValue     = originalEntity.RawValue,
                Value        = originalEntity.Value
            };

            entity.Properties.Insert(entity.Properties.IndexOf(originalEntity), fullEntity);

            //Add the condition operator if exists at the begin of the condition
            ViewProperty conditionOperator =
                entity.Properties.FirstOrDefault(x => x.Name.EqualsOrdinalIgnoreCase("ConditionOperator"));

            if (conditionOperator != null)
            {
                conditionOperator.IsHidden = true;
                fullEntity.Value           = $"{conditionOperator.Value} {fullEntity.Value}";
            }

            //Replace all the variables within [] in the condition with the values
            var             regex   = new Regex("\\[(.*?)\\]");
            MatchCollection matches = regex.Matches(fullEntity.Value);

            foreach (Match match in matches)
            {
                string       variableName = match.Groups[1].ToString();
                ViewProperty variable     = entity.Properties.FirstOrDefault(x => x.DisplayName.EqualsOrdinalIgnoreCase(variableName));

                if (variable == null && variableName.EqualsOrdinalIgnoreCase("Gift"))
                {
                    variable = entity.Properties.FirstOrDefault(x => x.Name.EqualsOrdinalIgnoreCase("TargetItemId"));
                }

                if (variable != null)
                {
                    variable.IsHidden = true;

                    string variableValue = await PrettifyVariableValue(variable, entity.Properties, commerceContext);

                    fullEntity.Value = fullEntity.Value.Replace(match.Value, $"<strong>{variableValue}</strong>");
                }
            }

            fullEntity.Value = fullEntity.Value.Replace("$", commerceContext.CurrentCurrency());

            // A quick and dirty resolution to let the content go over multiple lines.
            // Add extra div's with specific default classes because adding custom style is stripped by Angular.
            // The .dropdown-header class is for overwriting the white-space: nowrap, the .col-form-legend is for setting the font-size back to normal and .p-0 for removing the padding added by these classes
            fullEntity.Value =
                $"<div class='dropdown-header p-0 border-0'><div class='col-form-legend p-0'>{fullEntity.Value}</div></div>";
        }
Example #8
0
            public void Execute_ShouldRoundPriceCalc_True(
                BaseCartItemSubtotalPercentOffAction action,
                IRuleValue <decimal> subtotal,
                IRuleValue <decimal> percentOff,
                Cart cart,
                CommerceContext commerceContext,
                IRuleExecutionContext context)
            {
                /**********************************************
                * Arrange
                **********************************************/
                cart.Adjustments.Clear();
                cart.Lines.ForEach(l => l.Adjustments.Clear());

                var globalPricingPolicy = commerceContext.GetPolicy <GlobalPricingPolicy>();

                globalPricingPolicy.ShouldRoundPriceCalc         = true;
                globalPricingPolicy.RoundDigits                  = 3;
                globalPricingPolicy.MidPointRoundUp              = true;
                cart.Lines.ForEach(l => l.Totals.SubTotal.Amount = 100);
                var cartline = cart.Lines[1];

                cartline.Totals.SubTotal.Amount = 175;
                var cartTotals = new CartTotals(cart);

                subtotal.Yield(context).ReturnsForAnyArgs(150);
                percentOff.Yield(context).ReturnsForAnyArgs(33.3333333M);

                context.Fact <CommerceContext>().ReturnsForAnyArgs(commerceContext);
                commerceContext.AddObject(cartTotals);
                commerceContext.AddObject(cart);
                action.MatchingLines(context).ReturnsForAnyArgs(cart.Lines);
                action.SubtotalOperator = new DecimalGreaterThanEqualToOperator();
                action.Subtotal         = subtotal;
                action.PercentOff       = percentOff;

                /**********************************************
                * Act
                **********************************************/
                Action executeAction = () => action.Execute(context);

                /**********************************************
                * Assert
                **********************************************/
                executeAction.Should().NotThrow <Exception>();
                cart.Lines.SelectMany(l => l.Adjustments).Should().HaveCount(1);
                cart.Adjustments.Should().BeEmpty();
                cartTotals.Lines[cartline.Id].SubTotal.Amount.Should().Be(116.667M);
                cartline.Adjustments.Should().NotBeEmpty();
                cartline.Adjustments.FirstOrDefault().Should().NotBeNull();
                cartline.Adjustments.FirstOrDefault().Should().BeOfType <CartLineLevelAwardedAdjustment>();
                cartline.Adjustments.FirstOrDefault()?.Name.Should().Be(commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount);
                cartline.Adjustments.FirstOrDefault()?.DisplayName.Should().Be(commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount);
                cartline.Adjustments.FirstOrDefault()?.AdjustmentType.Should().Be(commerceContext.GetPolicy <KnownCartAdjustmentTypesPolicy>().Discount);
                cartline.Adjustments.FirstOrDefault()?.AwardingBlock.Should().Contain(nameof(BaseCartItemSubtotalPercentOffAction));
                cartline.Adjustments.FirstOrDefault()?.IsTaxable.Should().BeFalse();
                cartline.Adjustments.FirstOrDefault()?.Adjustment.CurrencyCode.Should().Be(commerceContext.CurrentCurrency());
                cartline.Adjustments.FirstOrDefault()?.Adjustment.Amount.Should().Be(-58.333M);
                cartline.HasComponent <MessagesComponent>().Should().BeTrue();
            }