public async void Should_qualify_when_operator_is_equal_and_fulfillment_method_is_same()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new CartFulfillmentConditionBuilder()
                                               .Equal()
                                               .WithValue("Standard"))
                                  .BenefitBy(new CartSubtotalPercentOffActionBuilder()
                                             .PercentOff(10))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            Cart cart = await new CartBuilder()
                        .WithStandardFulfillment()
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            Assert.Contains(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
        }
예제 #2
0
        private void TransformCore(CommerceContext commerceContext, string[] rawFields, InventoryInformation item)
        {
            var inventorySetName = rawFields[InventoryIdIndex];
            var productId        = rawFields[ProductIdIndex];

            int.TryParse(rawFields[QuantityIndex], out int quantity);

            string str = inventorySetName + "-" + productId;

            //if (!string.IsNullOrEmpty(arg.VariationId)) str = str + "-" + arg.VariationId;
            item.Id           = CommerceEntity.IdPrefix <InventoryInformation>() + str;
            item.FriendlyId   = str;
            item.InventorySet = new EntityReference(inventorySetName.ToEntityId <InventorySet>(), "");
            item.SellableItem = new EntityReference(productId.ToEntityId <SellableItem>(), "");
            //item.VariationId = arg.VariationId;
            item.Quantity = quantity;
            var component = item.GetComponent <ListMembershipsComponent>();

            component.Memberships.Add(CommerceEntity.ListName <InventoryInformation>());

            var component1 = item.GetComponent <PreorderableComponent>();
            //component1.Preorderable = result1;
            //component1.PreorderAvailabilityDate = new DateTimeOffset?();
            //component1.PreorderLimit = new int?(0);

            var component2 = item.GetComponent <BackorderableComponent>();
            //component2.Backorderable = result3;
            //component2.BackorderAvailabilityDate = new DateTimeOffset?();
            //component2.BackorderLimit = new int?(0);
        }
        public async void Should_not_qualify_when_customer_is_not_registered()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            var dateTime = new DateTimeOffset(new DateTime(2019, 12, 22));

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new LastPurchaseDateConditionBuilder()
                                               .Operator(Operator.Equal)
                                               .Date(dateTime))
                                  .BenefitBy(new CartSubtotalPercentOffActionBuilder()
                                             .PercentOff(10))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            Cart cart = await new CartBuilder().Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart = await client.GetJsonAsync <Cart>(
                "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components",
                new Dictionary <string, string>
            {
                { "IsRegistered", "false" }
            });

            Assert.DoesNotContain(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
        }
예제 #4
0
        public async Task <Setting> Process(CommerceContext commerceContext, CreateSettingArg arg)
        {
            using (var activity = CommandActivity.Start(commerceContext, this))
            {
                var setting = new Setting
                {
                    Id          = arg.Name.ToEntityId <Setting>(),
                    DisplayName = arg.DisplayName,
                    Name        = arg.Name,
                    IsActive    = false
                };

                var listMemberShipComponent = setting.GetComponent <ListMembershipsComponent>();
                if (!listMemberShipComponent.Memberships.Contains(CommerceEntity.ListName <Setting>()))
                {
                    listMemberShipComponent.Memberships.Add(CommerceEntity.ListName <Setting>());
                    setting.SetComponent(listMemberShipComponent);
                }

                var transientListMembershipComponent = setting.GetComponent <TransientListMembershipsComponent>();
                if (!transientListMembershipComponent.Memberships.Contains(CommerceEntity.ListName <Setting>()))
                {
                    transientListMembershipComponent.Memberships.Add(CommerceEntity.ListName <Setting>());
                    setting.SetComponent(transientListMembershipComponent);
                }

                var persistResult = await _commerceCommander.PersistEntity(commerceContext, setting);

                return(persistResult
                    ? setting
                    : null);
            }
        }
        public async void Should_benefit_fulfillment_fee_if_discount_is_higher_than_fee()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartAmountOffFulfillmentActionBuilder()
                                             .AmountOff(8)) // Fee = 5, Discount = 8
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder().Quantity(1).Price(50))
                        .WithStandardFulfillment()       // Default fulfillment fee = 5
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            AwardedAdjustment adjustment =
                resultCart.Adjustments.Single(x => x.AwardingBlock == nameof(CartAmountOffFulfillmentAction));

            Assert.Equal(-5, adjustment.Adjustment.Amount);

            // Subtotal = 50, Tax is 10% = 5, Fulfillment fee = 5 - 5 = 0
            Assert.Equal(55, resultCart.Totals.GrandTotal.Amount);
        }
예제 #6
0
        public override async Task <WishList> Run(GetWishListArgument arg, CommercePipelineExecutionContext context)
        {
            GetWishListBlock getWishListBlock = this;

            Condition.Requires <string>(arg.WishListId).IsNotNullOrEmpty("The WishListId can not be null or empty");
            List <WishList> objects = context.CommerceContext.GetObjects <WishList>();

            if (objects.Any() && objects.FirstOrDefault(p => p.Id == arg.WishListId) != null)
            {
                context.Logger.LogWarning($"{getWishListBlock.Name}.AlreadyLoaded: CartId:{arg}", Array.Empty <object>());
            }

            WishList wishlist = await getWishListBlock._findEntityPipeline.Run(new FindEntityArgument(typeof(WishList), arg.WishListId, true), context).ConfigureAwait(false) as WishList;

            if (wishlist == null || wishlist.IsPersisted)
            {
                return(wishlist);
            }

            wishlist.Id         = arg.WishListId;
            wishlist.Name       = arg.WishListName;
            wishlist.ShopName   = arg.ShopName;
            wishlist.CustomerId = arg.ShopperId;
            wishlist.SetComponent(new ListMembershipsComponent()
            {
                Memberships = new List <string>
                {
                    CommerceEntity.ListName <WishList>()
                }
            });

            return(wishlist);
        }
 protected override IEnumerable <string> GetListMemberships(
     CommercePipelineExecutionContext context)
 {
     return(new string[]
     {
         CommerceEntity.ListName <PriceCard>(),
     });
 }
        public async void Should_qualify_when_category_matches_multiple_orders()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Guid customerId = Guid.NewGuid();

            Order order = new OrderBuilder()
                          .WithLines(new LineBuilder()
                                     .Quantity(1)
                                     .Price(33)
                                     .InCategory("435345345"))
                          .Build();

            Order secondOrder = new OrderBuilder()
                                .WithLines(new LineBuilder()
                                           .Quantity(1)
                                           .Price(33)
                                           .InCategory("435345345"))
                                .Build();

            fixture.Factory.AddEntitiesToList(string.Format(CultureInfo.InvariantCulture, "Orders-ByCustomer-{0}", customerId),
                                              order, secondOrder);

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new OrderHistoryTotalInCategoryConditionBuilder()
                                               .Operator(Operator.Equal)
                                               .Total(66)       // Both orders have 1 product and total should be 2
                                               .ForCategory("Laptops"))
                                  .BenefitBy(new CartSubtotalPercentOffActionBuilder()
                                             .PercentOff(10))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder().Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart = await client.GetJsonAsync <Cart>(
                "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components",
                new Dictionary <string, string>
            {
                { "IsRegistered", "true" },
                { "CustomerId", customerId.ToString() }
            });

            Assert.Contains(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
        }
        public async void Should_match_operator(Operator @operator, int numberOfProductsInPromotion, int numberOfProductsInOrder,
                                                bool shouldQualify)
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Guid customerId = Guid.NewGuid();

            Order order = new OrderBuilder()
                          .WithLines(new LineBuilder()
                                     .Quantity(numberOfProductsInOrder)
                                     .InCategory("435345345"))
                          .Build();

            fixture.Factory.AddEntityToList(order,
                                            string.Format(CultureInfo.InvariantCulture, "Orders-ByCustomer-{0}", customerId));

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new OrderHistoryAmountInCategoryConditionBuilder()
                                               .Operator(@operator)
                                               .NumberOfProducts(numberOfProductsInPromotion)
                                               .ForCategory("Laptops"))
                                  .BenefitBy(new CartSubtotalPercentOffActionBuilder()
                                             .PercentOff(10))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder().Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart = await client.GetJsonAsync <Cart>(
                "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components",
                new Dictionary <string, string>
            {
                { "IsRegistered", "true" },
                { "CustomerId", customerId.ToString() }
            });

            if (shouldQualify)
            {
                Assert.Contains(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
            }
            else
            {
                Assert.DoesNotContain(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
            }
        }
예제 #10
0
        /// <summary>
        /// The execute.
        /// </summary>
        /// <param name="arg">
        /// The AddReviewArgument argument.
        /// </param>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// The <see cref="Review"/>.
        /// </returns>
        public override async Task <Review> Run(AddReviewArgument arg, CommercePipelineExecutionContext context)
        {
            AddReviewBlock addReviewBlock = this;

            Condition.Requires(arg).IsNotNull($"{addReviewBlock.Name}: The block argument cannot be null.");

            string reviewId = Guid.NewGuid().ToString();

            Review review = new Review
            {
                Id     = $"{CommerceEntity.IdPrefix<Review>()}{reviewId}",
                Text   = arg.ReviewsText,
                Author = arg.Author,
                Score  = arg.Score
            };

            DateTimeOffset?dateCreated = DateTimeOffset.UtcNow;

            review.DateCreated = dateCreated;
            DateTimeOffset?dateUpdated = DateTimeOffset.UtcNow;

            review.DateUpdated = dateUpdated;

            CommerceContext commerceContextRef = context.CommerceContext;

            string name = review.Name;

            review.ProductReference = new EntityReference()
            {
                EntityTarget = arg.Product.Id,
                Name         = arg.Product.Name
            };

            Review reviewRef = review;

            reviewRef.SetComponent(new ListMembershipsComponent()
            {
                Memberships = new List <string>()
                {
                    CommerceEntity.ListName <Review>()
                }
            });

            ReviewAddedModel reviewAdded = new ReviewAddedModel(review.FriendlyId)
            {
                Name = name
            };

            commerceContextRef.AddModel(reviewAdded);

            context.CommerceContext.AddUniqueObjectByType(arg);

            await context.CommerceContext.AddMessage(context.GetPolicy <KnownResultCodes>().Information, null, null, "Generated unallocated review");

            return(review);
        }
        public async void Should_benefit_multiple_times_when_within_action_limit()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartEveryXItemsInCategoryPriceDiscountActionBuilder()
                                             .AmountOff(10)
                                             .ForCategory("Laptops")
                                             .ItemsToAward(1)
                                             .ItemsToPurchase(2)
                                             .ApplyActionTo(ApplicationOrder.Ascending)
                                             .ActionLimit(2))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder().IdentifiedBy("001").Quantity(1).InCategory("435345345").Price(40),
                                   new LineBuilder().IdentifiedBy("002").Quantity(1).InCategory("435345345").Price(50),
                                   new LineBuilder().IdentifiedBy("003").Quantity(1).InCategory("435345345").Price(40),
                                   new LineBuilder().IdentifiedBy("004").Quantity(1).InCategory("435345345").Price(50))
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            CartLineComponent firstLine  = resultCart.Lines.Single(x => x.Id == "001");
            AwardedAdjustment adjustment =
                firstLine.Adjustments.Single(x => x.AwardingBlock == nameof(CartEveryXItemsInCategoryPriceDiscountAction));

            Assert.Equal(-10, adjustment.Adjustment.Amount);

            CartLineComponent secondLine       = resultCart.Lines.Single(x => x.Id == "003");
            AwardedAdjustment secondAdjustment =
                secondLine.Adjustments.Single(x => x.AwardingBlock == nameof(CartEveryXItemsInCategoryPriceDiscountAction));

            Assert.Equal(-10, secondAdjustment.Adjustment.Amount);

            // Subtotal = 160, Tax is 10% = 16, Fulfillment fee = 5
            Assert.Equal(181, resultCart.Totals.GrandTotal.Amount);
        }
예제 #12
0
        public async void Should_benefit()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartFreeGiftActionBuilder()
                                             .Quantity(1)
                                             .Gift("MyCatalog|999|"))
                                  .Build(fixture.Factory);

            var catalog = new Catalog
            {
                Id         = "Entity-Catalog-MyCatalog",
                FriendlyId = "MyCatalog",
                Name       = "MyCatalog"
            };

            SellableItem sellableItem = new SellableItemBuilder()
                                        .IdentifiedBy("001")
                                        .Priced(40)
                                        .Catalog("MyCatalog")
                                        .Build();

            SellableItem gift = new SellableItemBuilder()
                                .IdentifiedBy("999")
                                .Catalog("MyCatalog")
                                .Named("Free Gift")
                                .Priced(99)
                                .Build();

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder()
                                   .IdentifiedBy("001").WithProductId("MyCatalog|001|").Quantity(1).Price(40))
                        .Build();

            fixture.Factory.AddEntities(promotion, gift, sellableItem, catalog, cart);
            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            CartLineComponent giftLine = resultCart.Lines.Single(x => x.ItemId == "MyCatalog|999|");

            AwardedAdjustment adjustment = giftLine.Adjustments.Single(x => x.AwardingBlock == nameof(CartFreeGiftAction));

            Assert.Equal(-99, adjustment.Adjustment.Amount);

            // Subtotal = 40, Tax is 10% = 4, Fulfillment fee = 5
            Assert.Equal(49, resultCart.Totals.GrandTotal.Amount);
        }
예제 #13
0
        public async void Should_match_operator(Operator @operator, int numberOfProductsInPromotion, int numberOfProductsInCart,
                                                bool shouldQualify)
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartItemsMatchingInCategoryPercentageDiscountActionBuilder()
                                             .PercentageOff(50)
                                             .ForCategory("Laptops")
                                             .Operator(@operator)
                                             .NumberOfProducts(numberOfProductsInPromotion)
                                             .ApplyActionTo(ApplicationOrder.Ascending)
                                             .ActionLimit(numberOfProductsInPromotion))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder()
                                   .IdentifiedBy("001").Quantity(numberOfProductsInCart).InCategory("435345345").Price(40))
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            CartLineComponent line = resultCart.Lines.Single(x => x.Id == "001");

            if (shouldQualify)
            {
                Assert.Contains(line.Adjustments,
                                x => x.AwardingBlock == nameof(CartItemsMatchingInCategoryPercentageDiscountAction));
            }
            else
            {
                Assert.DoesNotContain(line.Adjustments,
                                      x => x.AwardingBlock == nameof(CartItemsMatchingInCategoryPercentageDiscountAction));
            }
        }
        /// <summary>
        /// Generates the sales activity.
        /// </summary>
        /// <param name="order">The order.</param>
        /// <param name="existingPayment">The existingPayment.</param>
        /// <param name="paymentToRefund">The payment to refund</param>
        /// <param name="refundTransactionId">The refund transaction identifier.</param>
        /// <param name="context">The context.</param>
        /// <returns>
        /// A <see cref="Task" />
        /// </returns>
        protected virtual async Task GenerateSalesActivity(Order order, PaymentComponent existingPayment, PaymentComponent paymentToRefund, string refundTransactionId, CommercePipelineExecutionContext context)
        {
            var salesActivity = new SalesActivity
            {
                Id             = $"{CommerceEntity.IdPrefix<SalesActivity>()}{Guid.NewGuid():N}",
                ActivityAmount = new Money(existingPayment.Amount.CurrencyCode, paymentToRefund.Amount.Amount * -1),
                Customer       = new EntityReference
                {
                    EntityTarget = order.EntityComponents.OfType <ContactComponent>().FirstOrDefault()?.CustomerId
                },
                Order = new EntityReference
                {
                    EntityTarget         = order.Id,
                    EntityTargetUniqueId = order.UniqueId
                },
                Name          = "Refund the Federated Payment",
                PaymentStatus = context.GetPolicy <KnownSalesActivityStatusesPolicy>().Completed
            };

            salesActivity.SetComponent(new ListMembershipsComponent
            {
                Memberships = new List <string>
                {
                    CommerceEntity.ListName <SalesActivity>(),
                    context.GetPolicy <KnownOrderListsPolicy>().SalesCredits,
                    string.Format(CultureInfo.InvariantCulture, context.GetPolicy <KnownOrderListsPolicy>().OrderSalesActivities, order.FriendlyId)
                }
            });

            if (existingPayment.Amount.Amount != paymentToRefund.Amount.Amount)
            {
                salesActivity.SetComponent(existingPayment);
            }

            if (!string.IsNullOrEmpty(refundTransactionId))
            {
                salesActivity.SetComponent(new TransactionInformationComponent(refundTransactionId));
            }

            var salesActivities = order.SalesActivity.ToList();

            salesActivities.Add(new EntityReference
            {
                EntityTarget         = salesActivity.Id,
                EntityTargetUniqueId = salesActivity.UniqueId
            });
            order.SalesActivity = salesActivities;

            await _persistPipeline.Run(new PersistEntityArgument(salesActivity), context).ConfigureAwait(false);
        }
        public virtual async Task <Cart> Process(CommerceContext commerceContext, string wishlistId, CartLineComponent line)
        {
            AddWishListLineItemCommand addCartLineCommand = this;
            Cart result = (Cart)null;

            using (CommandActivity.Start(commerceContext, (CommerceCommand)addCartLineCommand))
            {
                await addCartLineCommand.PerformTransaction(commerceContext, (Func <Task>)(async() =>
                {
                    FindEntityArgument findEntityArgument = new FindEntityArgument(typeof(Cart), wishlistId, true);
                    var context = commerceContext.GetPipelineContextOptions();

                    Cart cart = await this._getPipeline.Run(findEntityArgument, (IPipelineExecutionContextOptions)commerceContext.GetPipelineContextOptions()).ConfigureAwait(false) as Cart;
                    if (cart == null)
                    {
                        string str = await context.CommerceContext.AddMessage(commerceContext.GetPolicy <KnownResultCodes>().ValidationError, "EntityNotFound", new object[1]
                        {
                            (object)wishlistId
                        }, string.Format("Entity {0} was not found.", (object)wishlistId));
                    }
                    else
                    {
                        if (!cart.IsPersisted)
                        {
                            cart.Id       = wishlistId;
                            cart.Name     = wishlistId;
                            cart.ShopName = commerceContext.CurrentShopName();
                            cart.SetComponent((Component) new ListMembershipsComponent()
                            {
                                Memberships = (IList <string>) new List <string>()
                                {
                                    CommerceEntity.ListName <Cart>()
                                }
                            });

                            cart.SetComponent(new CartTypeComponent()
                            {
                                CartType = CartTypeEnum.Wishlist.ToString()
                            });
                        }


                        result = await this._addWishListLineItemPipeli.Run(new CartLineArgument(cart, line), (IPipelineExecutionContextOptions)context);
                    }
                }));
            }

            return(result);
        }
        public override async Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context)
        {
            Contract.Requires(entityView != null);
            Contract.Requires(context != null);
            Condition.Requires(entityView).IsNotNull($"{this.Name}: The argument cannot be null");
            if (entityView.Name != "VatTaxDashboard")
            {
                return(entityView);
            }
            //var pluginPolicy = context.GetPolicy<PluginPolicy>();

            var newEntityViewTable = entityView;

            entityView.UiHint = "Table";
            entityView.Icon   = "money_dollar";
            entityView.ItemId = string.Empty;

            var sampleDashboardEntities = await _commerceCommander.Command <ListCommander>()
                                          .GetListItems <VatTaxEntity>(context.CommerceContext,
                                                                       CommerceEntity.ListName <VatTaxEntity>(), 0, 99).ConfigureAwait(false);

            //var sampleDashboardEntities = await this._commerceCommander.Command<ListCommander>().GetListItems<VatTaxEntity>(context.CommerceContext,CommerceEntity.ListName<VatTaxEntity>(), 0, 99);
            foreach (var sampleDashboardEntity in sampleDashboardEntities)
            {
                newEntityViewTable.ChildViews.Add(
                    new EntityView
                {
                    ItemId     = sampleDashboardEntity.Id,
                    Icon       = "money_dollar",
                    Properties = new List <ViewProperty>
                    {
                        new ViewProperty {
                            Name = "TaxTag", RawValue = sampleDashboardEntity.TaxTag
                        },
                        new ViewProperty {
                            Name = "CountryCode", RawValue = sampleDashboardEntity.CountryCode
                        },
                        new ViewProperty {
                            Name = "TaxPct", RawValue = sampleDashboardEntity.TaxPct
                        }
                    }
                });
            }


            /* STUDENT: Complete the body of the Run method. You should handle the
             * entity view for both a new and existing entity. */
            return(entityView);
        }
예제 #17
0
        private void TransformCore(CommerceContext commerceContext, string[] rawFields, Category item)
        {
            var catalogName = rawFields[CatalogNameIndex];

            item.Name        = rawFields[CategoryNameIndex];
            item.Id          = item.Name.ToCategoryId(catalogName);
            item.FriendlyId  = item.Name.ToCategoryFriendlyId(catalogName);
            item.SitecoreId  = GuidUtils.GetDeterministicGuidString(item.Id);
            item.DisplayName = rawFields[CategoryDisplayNameIndex];
            //item.Description = arg.Description;
            var component = item.GetComponent <ListMembershipsComponent>();

            component.Memberships.Add(string.Format("{0}", CommerceEntity.ListName <Category>()));
            component.Memberships.Add(commerceContext.GetPolicy <KnownCatalogListsPolicy>().CatalogItems);
        }
예제 #18
0
        public async void Should_benefit_in_descending_order_when_category_matches()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartItemsMatchingInCategoryPercentageDiscountActionBuilder()
                                             .PercentageOff(50)
                                             .ForCategory("Laptops")
                                             .Operator(Operator.Equal)
                                             .NumberOfProducts(2)
                                             .ApplyActionTo(ApplicationOrder.Descending)
                                             .ActionLimit(1))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder().IdentifiedBy("001").Quantity(1).InCategory("435345345").Price(40),
                                   new LineBuilder().IdentifiedBy("002").Quantity(1).InCategory("435345345").Price(50))
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            CartLineComponent line       = resultCart.Lines.Single(x => x.Id == "002");
            AwardedAdjustment adjustment = line.Adjustments.Single(x =>
                                                                   x.AwardingBlock ==
                                                                   nameof(CartItemsMatchingInCategoryPercentageDiscountAction));

            Assert.Equal(-25, adjustment.Adjustment.Amount);

            // Subtotal = 65, Tax is 10% = 6.5, Fulfillment fee = 5
            Assert.Equal(76.5m, resultCart.Totals.GrandTotal.Amount);
        }
        /// <summary>
        /// Bootstraps the audio.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns>A <see cref="Task"/></returns>
        private async Task BootstrapAudio(CommercePipelineExecutionContext context)
        {
            var item = new SellableItem
            {
                Components = new List <Component>
                {
                    new CatalogComponent {
                        Name = "Habitat_Mater"
                    },
                    new ListMembershipsComponent
                    {
                        Memberships = new List <string> {
                            CommerceEntity.ListName <SellableItem>()
                        }
                    },
                    new ItemVariationsComponent
                    {
                        ChildComponents = new List <Component>
                        {
                            new ItemVariationComponent
                            {
                                Id       = "56042122",
                                Name     = "XSound 7” CD DVD, In-Dash Receiver, 3-Way Speakers, and HabitatPro Installation",
                                Policies = new List <Policy>
                                {
                                    new ListPricingPolicy(new List <Money> {
                                        new Money("USD", 423.99M), new Money("CAD", 424.99M)
                                    })
                                },
                                ChildComponents = new List <Component>
                                {
                                    new PhysicalItemComponent()
                                }
                            }
                        }
                    }
                },
                Policies = new List <Policy> {
                    new ListPricingPolicy(new List <Money> {
                        new Money("USD", 423.99M), new Money("CAD", 424.99M)
                    })
                },
                Id   = $"{CommerceEntity.IdPrefix<SellableItem>()}6042122",
                Name = "XSound 7” CD DVD, In-Dash Receiver, 3-Way Speakers, and HabitatPro Installation"
            };

            await this._persistEntityPipeline.Run(new PersistEntityArgument(item), context);
        }
예제 #20
0
        public async void Should_match_operator(Operator @operator, DateTimeOffset promotionDate, DateTimeOffset firstOrderDate,
                                                bool shouldQualify)
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Guid customerId = Guid.NewGuid();

            Order order = new OrderBuilder().PlacedOn(firstOrderDate).Build();

            Order laterOrder = new OrderBuilder().PlacedOn(firstOrderDate.AddDays(100)).Build();

            fixture.Factory.AddEntitiesToList(string.Format(CultureInfo.InvariantCulture, "Orders-ByCustomer-{0}", customerId),
                                              order, laterOrder);

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new FirstPurchaseDateConditionBuilder()
                                               .Operator(@operator)
                                               .Date(promotionDate))
                                  .BenefitBy(new CartSubtotalPercentOffActionBuilder()
                                             .PercentOff(10))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            Cart cart = await new CartBuilder().Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart = await client.GetJsonAsync <Cart>(
                "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components",
                new Dictionary <string, string>
            {
                { "IsRegistered", "true" },
                { "CustomerId", customerId.ToString() }
            });

            if (shouldQualify)
            {
                Assert.Contains(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
            }
            else
            {
                Assert.DoesNotContain(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
            }
        }
예제 #21
0
        /// <summary>
        /// Executes the pipeline block.
        /// </summary>
        /// <param name="arg">The entity view.</param>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public override async Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context)
        {
            Condition.Requires(entityView).IsNotNull($"{Name}: The argument cannot be null");

            var viewsPolicy        = context.GetPolicy <Policies.KnownInventoryViewsPolicy>();
            var entityViewArgument = context.CommerceContext.GetObject <EntityViewArgument>();
            var enablementPolicy   = context.GetPolicy <Policies.InventoryFeatureEnablementPolicy>();

            if (!enablementPolicy.InventoryFromProductView ||
                string.IsNullOrEmpty(entityViewArgument?.ViewName) ||
                !entityViewArgument.ViewName.Equals(viewsPolicy.SelectInventorySet, StringComparison.OrdinalIgnoreCase))
            {
                return(await Task.FromResult(entityView).ConfigureAwait(false));
            }

            var inventorySets =
                await CommerceCommander.Pipeline <FindEntitiesInListPipeline>().Run(
                    new FindEntitiesInListArgument(
                        typeof(InventorySet),
                        $"{CommerceEntity.ListName<InventorySet>()}",
                        0,
                        int.MaxValue),
                    context).ConfigureAwait(false);

            var availableSelectionsPolicy = new AvailableSelectionsPolicy(
                inventorySets.List.Items.Select(s =>
                                                new Selection {
                DisplayName = s.DisplayName, Name = s.Name
            }).ToList()
                ?? new List <Selection>());

            var viewProperty = new ViewProperty()
            {
                Name     = "Inventory Set",
                UiType   = "SelectList",
                Policies = new List <Policy>()
                {
                    availableSelectionsPolicy
                },
                RawValue =
                    availableSelectionsPolicy.List.Where(s => s.IsDefault).FirstOrDefault()?.Name
                    ?? availableSelectionsPolicy.List?.FirstOrDefault().Name
            };

            entityView.Properties.Add(viewProperty);

            return(entityView);
        }
예제 #22
0
        /// <summary>
        /// The execute.
        /// </summary>
        /// <param name="arg">
        /// The AddJobConnectionArgument argument.
        /// </param>
        /// <param name="context">
        /// The context.
        /// </param>
        /// <returns>
        /// The <see cref="JobConnection"/>.
        /// </returns>
        public override async Task <JobConnection> Run(AddJobConnectionArgument arg, CommercePipelineExecutionContext context)
        {
            Condition.Requires <AddJobConnectionArgument>(arg).IsNotNull <AddJobConnectionArgument>("AddJobConnectionArgument The argument cannot be null.");
            Condition.Requires <string>(arg.Name).IsNotNullOrEmpty("The Job Connection name cannot be null or empty.");
            Condition.Requires <string>(arg.Type).IsNotNullOrEmpty("The Job Connection type cannot be null or empty.");
            TaskAwaiter <bool> awaiter = _findEntityPipeline.Run(new FindEntityArgument(typeof(JobConnection),
                                                                                        $"{(object) CommerceEntity.IdPrefix<JobConnection>()}{ arg.Name}"), context).GetAwaiter();

            if (awaiter.GetResult())
            {
                CommerceContext commerceContext = context.CommerceContext;
                string          validationError = context.GetPolicy <KnownResultCodes>().ValidationError;
                string          commerceTermKey = "JobConnectionNameAlreadyInUse";
                object[]        args            = new object[1] {
                    (object)arg.Name
                };
                string defaultMessage = $"Job Connection name {(object) arg.Name} is already in use.";
                context.Abort("Ok|" + await commerceContext.AddMessage(validationError, commerceTermKey, args, defaultMessage), context);
                context = null;
                return(null);
            }
            JobConnection jobConnection = new JobConnection(arg.Name, arg.Type);

            jobConnection.Id          = $"{ CommerceEntity.IdPrefix<JobConnection>()}{ arg.Name}";
            jobConnection.FriendlyId  = $"{arg.Name}";;
            jobConnection.Description = arg.Description;;
            jobConnection.DisplayName = arg.DisplayName;
            var jobConnectionPolicy = context.GetPolicy <JobConnectionPolicy>();

            jobConnectionPolicy.DbConnectionString = arg.DbConnectionString;
            jobConnectionPolicy.WebServiceUrl      = arg.WebServiceUrl;
            jobConnectionPolicy.Username           = arg.Username;
            jobConnectionPolicy.Password           = arg.Password;
            jobConnection.SetPolicy(jobConnectionPolicy);
            jobConnection.SetComponent(new ListMembershipsComponent()
            {
                Memberships = new List <string>()
                {
                    CommerceEntity.ListName <JobConnection>()
                }
            });
            JobConnectionAdded jobConnectionAdded = new JobConnectionAdded(jobConnection.FriendlyId);

            jobConnectionAdded.Name = jobConnection.Name;
            context.CommerceContext.AddModel(jobConnectionAdded);
            return(jobConnection);
        }
        public async void Should_match_operator(Operator @operator, int totalRequired, int totalInCart, bool shouldQualify)
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new CartProductTotalInCategoryConditionBuilder()
                                               .Operator(@operator)
                                               .Total(totalRequired)
                                               .ForCategory("Laptops")
                                               .DoesNotIncludeSubCategories())
                                  .BenefitBy(new CartSubtotalPercentOffActionBuilder()
                                             .PercentOff(10))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder()
                                   .Quantity(1)
                                   .Price(totalInCart)
                                   .InCategory("435345345"))
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            if (shouldQualify)
            {
                Assert.Contains(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
            }
            else
            {
                Assert.DoesNotContain(resultCart.Adjustments, c => c.AwardingBlock == nameof(CartSubtotalPercentOffAction));
            }
        }
        private async Task GenerateSalesActivity(Order order,
                                                 PaymentComponent existingPayment,
                                                 PaymentComponent paymentToRefund,
                                                 CommercePipelineExecutionContext context)
        {
            var salesActivity = new SalesActivity
            {
                Id             = $"{CommerceEntity.IdPrefix<SalesActivity>()}{Guid.NewGuid():N}",
                ActivityAmount = new Money(existingPayment.Amount.CurrencyCode, paymentToRefund.Amount.Amount * -1),
                Customer       = new EntityReference
                {
                    EntityTarget = order.EntityComponents.OfType <ContactComponent>().FirstOrDefault()?.CustomerId
                },
                Order = new EntityReference
                {
                    EntityTarget = order.Id
                },
                Name          = "Simple Payment Refund",
                PaymentStatus = context.GetPolicy <KnownSalesActivityStatusesPolicy>().Completed
            };

            // Add the new sales activity to the OrderSalesActivities list
            salesActivity.SetComponent(new ListMembershipsComponent
            {
                Memberships = new List <string>
                {
                    CommerceEntity.ListName <SalesActivity>(),
                    context.GetPolicy <KnownOrderListsPolicy>().SalesCredits,
                    string.Format(context.GetPolicy <KnownOrderListsPolicy>().OrderSalesActivities, order.FriendlyId)
                }
            });

            if (existingPayment.Amount.Amount != paymentToRefund.Amount.Amount)
            {
                salesActivity.SetComponent(existingPayment);
            }

            var salesActivities = order.SalesActivity.ToList();

            salesActivities.Add(new EntityReference {
                EntityTarget = salesActivity.Id
            });
            order.SalesActivity = salesActivities;

            await Commander.PersistEntity(context.CommerceContext, salesActivity);
        }
        /// <summary>
        /// Processes the specified commerce context.
        /// </summary>
        /// <param name="commerceContext">The commerce context.</param>
        /// <returns>
        /// Number of migrated customers
        /// </returns>
        public virtual async Task <int> Process(CommerceContext commerceContext)
        {
            using (CommandActivity.Start(commerceContext, this))
            {
                var context  = commerceContext.GetPipelineContextOptions();
                var listName = CommerceEntity.ListName <Customer>();

                var result = await this.Command <GetListMetadataCommand>().Process(commerceContext, listName);

                if (result == null)
                {
                    await commerceContext.AddMessage(
                        commerceContext.GetPolicy <KnownResultCodes>().Error,
                        "EntityNotFound",
                        new object[] { listName },
                        $"There is no customers in the list {listName}.");

                    return(0);
                }

                if (result.Count == 0)
                {
                    await context.CommerceContext.AddMessage(
                        context.CommerceContext.GetPolicy <KnownResultCodes>().Error,
                        "EntityNotFound",
                        new object[] { listName },
                        $"There is no customers in the list {listName}.");

                    return(0);
                }

                int customersCount = 0;
                int skip           = 0;
                int take           = 20;

                while (customersCount < result.Count)
                {
                    customersCount += await this.UpgradeCustomersInList(context, listName, skip, take);

                    skip += take;
                }

                return(customersCount);
            }
        }
예제 #26
0
        public override async Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context)
        {
            Condition.Requires(entityView).IsNotNull($"{this.Name}: The argument cannot be null");

            if (entityView.Name != "VatTaxDashboard")
            {
                return(entityView);
            }

            var pluginPolicy = context.GetPolicy <PluginPolicy>();

            var newEntityViewTable = entityView;

            entityView.UiHint = "Table";
            entityView.Icon   = pluginPolicy.Icon;
            entityView.ItemId = string.Empty;

            var sampleDashboardEntities = await this._commerceCommander.Command <ListCommander>()
                                          .GetListItems <VatTaxTableEntity>(context.CommerceContext,
                                                                            CommerceEntity.ListName <VatTaxTableEntity>(), 0, 99);

            foreach (var sampleDashboardEntity in sampleDashboardEntities)
            {
                newEntityViewTable.ChildViews.Add(
                    new EntityView
                {
                    ItemId     = sampleDashboardEntity.Id,
                    Icon       = pluginPolicy.Icon,
                    Properties = new List <ViewProperty>
                    {
                        new ViewProperty {
                            Name = "TaxTag", RawValue = sampleDashboardEntity.TaxTag
                        },
                        new ViewProperty {
                            Name = "CountryCode", RawValue = sampleDashboardEntity.CountryCode
                        },
                        new ViewProperty {
                            Name = "TaxPct", RawValue = sampleDashboardEntity.TaxPct
                        }
                    }
                });
            }

            return(entityView);
        }
예제 #27
0
        public async void Should_not_benefit_when_category_does_not_match()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartEveryXItemsInCategoryPercentageDiscountActionBuilder()
                                             .PercentageOff(50)
                                             .ForCategory("Laptops")
                                             .ItemsToAward(1)
                                             .ItemsToPurchase(2)
                                             .ApplyActionTo(ApplicationOrder.Ascending)
                                             .ActionLimit(1))
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            fixture.Factory.AddEntity(new Category
            {
                Id         = "Laptops".ToEntityId <Category>(),
                SitecoreId = "435345345"
            });

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder().IdentifiedBy("001").Quantity(1).InCategory("34345454").Price(40),
                                   new LineBuilder().IdentifiedBy("002").Quantity(1).InCategory("454545454").Price(50))
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            CartLineComponent line = resultCart.Lines.Single(x => x.Id == "002");

            Assert.DoesNotContain(line.Adjustments,
                                  x => x.AwardingBlock == nameof(CartEveryXItemsInCategoryPercentageDiscountAction));
        }
        public async void Should_benefit_split_fulfillments()
        {
            fixture.Factory.ClearAllEntities();

            HttpClient client = fixture.Factory.CreateClient();

            Promotion promotion = await new PromotionBuilder()
                                  .QualifiedBy(new IsCurrentDayConditionBuilder()
                                               .Day(DateTime.Now.Day))
                                  .BenefitBy(new CartAmountOffFulfillmentActionBuilder()
                                             .AmountOff(3)) // Fee = 2 * 2, Discount = 3
                                  .Build(fixture.Factory);

            fixture.Factory.AddEntityToList(promotion, CommerceEntity.ListName <Promotion>());
            fixture.Factory.AddEntity(promotion);

            Cart cart = await new CartBuilder()
                        .WithLines(new LineBuilder()
                                   .IdentifiedBy("001")
                                   .Quantity(1)
                                   .WithStandardFulfillment()       // Default fulfillment fee per line item is 2
                                   .Price(50), new LineBuilder()
                                   .IdentifiedBy("002")
                                   .Quantity(1)
                                   .WithStandardFulfillment()                   // Default fulfillment fee per line item is 2
                                   .Price(50))
                        .WithSplitFulfillment()
                        .Build();

            fixture.Factory.AddEntity(cart);

            Cart resultCart =
                await client.GetJsonAsync <Cart>(
                    "api/Carts('Cart01')?$expand=Lines($expand=CartLineComponents($expand=ChildComponents)),Components");

            AwardedAdjustment adjustment =
                resultCart.Adjustments.Single(x => x.AwardingBlock == nameof(CartAmountOffFulfillmentAction));

            Assert.Equal(-3, adjustment.Adjustment.Amount);

            // Subtotal = 100, Tax is 10% = 10, Fulfillment fee = 2*2 - 3 = 1
            Assert.Equal(111, resultCart.Totals.GrandTotal.Amount);
        }
        private Shop CreateShop(string id, string name, string displayName, string friendlyId = null)
        {
            var shop = new Shop
            {
                Id          = id,
                Name        = name,
                DisplayName = displayName,
                FriendlyId  = friendlyId
            };

            shop.AddComponents(new ListMembershipsComponent
            {
                Memberships = new List <string>
                {
                    CommerceEntity.ListName <Shop>()
                }
            });

            return(shop);
        }
        /// <summary>
        /// Generates the sales activity.
        /// </summary>
        /// <param name="order">The order.</param>
        /// <param name="payment">The payment.</param>
        /// <param name="context">The context.</param>
        /// <returns>A <see cref="Task"/></returns>
        protected virtual async Task GenerateSalesActivity(Order order, PaymentComponent payment, CommercePipelineExecutionContext context)
        {
            var salesActivity = new SalesActivity
            {
                Id             = CommerceEntity.IdPrefix <SalesActivity>() + Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture),
                ActivityAmount = new Money(payment.Amount.CurrencyCode, 0),
                Customer       = new EntityReference
                {
                    EntityTarget = order.EntityComponents.OfType <ContactComponent>().FirstOrDefault()?.CustomerId
                },
                Order = new EntityReference
                {
                    EntityTarget         = order.Id,
                    EntityTargetUniqueId = order.UniqueId
                },
                Name          = "Void the Federated payment",
                PaymentStatus = context.GetPolicy <KnownSalesActivityStatusesPolicy>().Void
            };

            salesActivity.SetComponent(new ListMembershipsComponent
            {
                Memberships = new List <string>
                {
                    CommerceEntity.ListName <SalesActivity>(),
                    string.Format(CultureInfo.InvariantCulture, context.GetPolicy <KnownOrderListsPolicy>().OrderSalesActivities, order.FriendlyId)
                }
            });

            salesActivity.SetComponent(payment);

            var salesActivities = order.SalesActivity.ToList();

            salesActivities.Add(new EntityReference
            {
                EntityTarget         = salesActivity.Id,
                EntityTargetUniqueId = salesActivity.UniqueId
            });
            order.SalesActivity = salesActivities;

            await _persistEntityPipeline.Run(new PersistEntityArgument(salesActivity), context).ConfigureAwait(false);
        }