コード例 #1
0
        public ItemQtyAdjustmentValidator(CartAggregate cartAggr)
        {
            RuleFor(x => x.NewQuantity).GreaterThan(0);
            RuleFor(x => x.LineItemId).NotNull();
            RuleFor(x => x.CartProduct).NotNull();
            RuleFor(x => x).Custom((qtyAdjust, context) =>
            {
                var lineItem = cartAggr.Cart?.Items?.FirstOrDefault(x => x.Id.EqualsInvariant(qtyAdjust.LineItemId));
                if (lineItem == null)
                {
                    context.AddFailure(CartErrorDescriber.LineItemWithGivenIdNotFound(new LineItem {
                        Id = qtyAdjust.LineItemId
                    }));
                }
                else if (lineItem.IsReadOnly)
                {
                    context.AddFailure(CartErrorDescriber.LineItemIsReadOnly(lineItem));
                }

                if (qtyAdjust.CartProduct != null && !new ProductIsAvailableSpecification().IsSatisfiedBy(qtyAdjust.CartProduct, qtyAdjust.NewQuantity))
                {
                    context.AddFailure(CartErrorDescriber.ProductQtyInsufficientError(qtyAdjust.CartProduct, qtyAdjust.NewQuantity, qtyAdjust.CartProduct.AvailableQuantity));
                }
            });
        }
コード例 #2
0
        public NewCartItemValidator()
        {
            RuleFor(x => x.Quantity).GreaterThan(0);
            RuleFor(x => x.ProductId).NotNull();
            RuleFor(x => x.CartProduct).NotNull();

            RuleSet("strict", () =>
            {
                RuleFor(x => x).Custom((newCartItem, context) =>
                {
                    if (newCartItem.CartProduct != null && !AbstractTypeFactory <ProductIsAvailableSpecification> .TryCreateInstance().IsSatisfiedBy(newCartItem.CartProduct, newCartItem.Quantity))
                    {
                        context.AddFailure(CartErrorDescriber.ProductUnavailableError(newCartItem.CartProduct));
                    }
                    if (newCartItem.Price != null)
                    {
                        var productSalePrice = newCartItem.CartProduct.Price.GetTierPrice(newCartItem.Quantity).Price;

                        if (newCartItem.Price < productSalePrice.Amount)
                        {
                            context.AddFailure(CartErrorDescriber.UnableToSetLessPrice(newCartItem.CartProduct));
                        }
                    }
                });
            });
        }
        public async Task ValidateItemQtyAdjustment_ProductIsUnavailable_Invalid()
        {
            // Arrange
            var aggregate = GetValidCartAggregate();

            var lineItem = _fixture.Create <LineItem>();

            aggregate.Cart.Items = new List <LineItem> {
                lineItem
            };

            var item = _fixture
                       .Build <ItemQtyAdjustment>()
                       .With(x => x.LineItemId, lineItem.Id)
                       .Create();

            var validator = new ItemQtyAdjustmentValidator();

            // Act
            var result = await validator.ValidateAsync(item);

            var expected = CartErrorDescriber.ProductQtyInsufficientError(
                item.CartProduct,
                item.NewQuantity,
                item.CartProduct.AvailableQuantity);

            // Assert
            result.Errors.Should().Contain(x =>
                                           x.ErrorMessage == expected.ErrorMessage &&
                                           x.ErrorCode == expected.ErrorCode);
        }
コード例 #4
0
        public CartLineItemValidator(IEnumerable <CartProduct> allCartProducts)
        {
            RuleSet("strict", () =>
            {
                RuleFor(x => x).Custom((lineItem, context) =>
                {
                    var cartProduct = allCartProducts.FirstOrDefault(x => x.Id.EqualsInvariant(lineItem.ProductId));
                    if (cartProduct == null || !AbstractTypeFactory <ProductIsBuyableSpecification> .TryCreateInstance().IsSatisfiedBy(cartProduct))
                    {
                        context.AddFailure(CartErrorDescriber.ProductUnavailableError(lineItem));
                    }
                    else
                    {
                        var isProductAvailable = AbstractTypeFactory <ProductIsAvailableSpecification> .TryCreateInstance().IsSatisfiedBy(cartProduct, lineItem.Quantity);
                        if (!isProductAvailable)
                        {
                            context.AddFailure(CartErrorDescriber.ProductQtyChangedError(lineItem, cartProduct.AvailableQuantity));
                        }

                        var tierPrice = cartProduct.Price.GetTierPrice(lineItem.Quantity);
                        if (tierPrice.Price.Amount > lineItem.SalePrice)
                        {
                            context.AddFailure(CartErrorDescriber.ProductPriceChangedError(lineItem, lineItem.SalePrice, lineItem.SalePriceWithTax, tierPrice.Price.Amount, tierPrice.PriceWithTax.Amount));
                        }
                    }
                });
            });
        }
        public async Task ValidateItemQtyAdjustment_LineItemIsReadOnly_Invalid()
        {
            // Arrange
            var aggregate = GetValidCartAggregate();

            var lineItem = _fixture
                           .Build <LineItem>()
                           .With(x => x.IsReadOnly, true)
                           .Create();

            aggregate.Cart.Items = new List <LineItem> {
                lineItem
            };

            var item = _fixture
                       .Build <ItemQtyAdjustment>()
                       .With(x => x.LineItemId, lineItem.Id)
                       .With(x => x.LineItem, lineItem)
                       .Create();

            var validator = new ItemQtyAdjustmentValidator();

            // Act
            var result = await validator.ValidateAsync(item);

            var expected = CartErrorDescriber.LineItemIsReadOnly(lineItem);

            // Assert
            result.Errors.Should().Contain(x =>
                                           x.ErrorMessage == expected.ErrorMessage &&
                                           x.ErrorCode == expected.ErrorCode);
        }
        public async Task <BulkCartResult> Handle(AddCartItemsBulkCommand request, CancellationToken cancellationToken)
        {
            var result         = new BulkCartResult();
            var cartItemsToAdd = new List <NewCartItem>();

            // find missing skus
            var products = await FindProductsBySkuAsync(request);

            foreach (var item in request.CartItems)
            {
                var product = products.FirstOrDefault(x => x.Code == item.ProductSku);
                if (product != null)
                {
                    var newCartItem = new NewCartItem(product.Id, item.Quantity);
                    cartItemsToAdd.Add(newCartItem);
                }
                else
                {
                    var error = CartErrorDescriber.BulkInvalidProductError(nameof(CatalogProduct), item.ProductSku);
                    result.Errors.Add(error);
                }
            }

            // send Add to Cart command
            var command = new AddCartItemsCommand
            {
                CartId       = request.CartId,
                StoreId      = request.StoreId,
                CartType     = request.CartType,
                CartName     = request.CartName,
                UserId       = request.UserId,
                CurrencyCode = request.CurrencyCode,
                CultureName  = request.CultureName,
                CartItems    = cartItemsToAdd.ToArray(),
            };

            var cartAggregate = await _mediator.Send(command, cancellationToken);

            result.Cart = cartAggregate;

            // transform cart product unavaliable validation erorrs to human readable
            var lineItemErrors = cartAggregate.ValidationErrors
                                 .OfType <CartValidationError>()
                                 .Where(x => x.ObjectType == "CartProduct" && x.ErrorCode == "CART_PRODUCT_UNAVAILABLE")
                                 .Select(x =>
            {
                var sku   = products.FirstOrDefault(p => p.Id == x.ObjectId)?.Code ?? x.ObjectId;
                var error = CartErrorDescriber.BulkProductUnavailableError(nameof(CatalogProduct), sku);
                return(error);
            });

            result.Errors.AddRange(lineItemErrors);

            return(result);
        }
コード例 #7
0
        public async Task ValidatePayment_PaymentGatewayNotContainingInAvailPaymentMethods_Valid()
        {
            // Arrange
            _context.AvailPaymentMethods = _fixture.CreateMany <PaymentMethod>().ToList();
            var item = _fixture.Create <Payment>();

            // Act
            var validator = new CartPaymentValidator(_context.AvailPaymentMethods);
            var result    = await validator.ValidateAsync(item, ruleSet : "strict");

            // Assert
            var expected = CartErrorDescriber.PaymentMethodUnavailable(item, item.PaymentGatewayCode);

            result.Errors.Should().Contain(x =>
                                           x.ErrorMessage == expected.ErrorMessage &&
                                           x.ErrorCode == expected.ErrorCode);
        }
コード例 #8
0
        public CartPaymentValidator()
        {
            //To support the use case for partial payment update when user sets the address first.
            //RuleFor(x => x.PaymentGatewayCode).NotNull().NotEmpty();
            RuleFor(x => x).Custom((paymentContext, context) =>
            {
                var availPaymentMethods = paymentContext.AvailPaymentMethods;
                var payment             = paymentContext.Payment;

                if (availPaymentMethods != null && !string.IsNullOrEmpty(payment.PaymentGatewayCode))
                {
                    var paymentMethod = availPaymentMethods.FirstOrDefault(x => payment.PaymentGatewayCode.EqualsInvariant(x.Code));
                    if (paymentMethod == null)
                    {
                        context.AddFailure(CartErrorDescriber.PaymentMethodUnavailable(payment, payment.PaymentGatewayCode));
                    }
                }
            });
        }
 public ChangeCartItemPriceValidator(CartAggregate cartAggr)
 {
     RuleFor(x => x.NewPrice).GreaterThanOrEqualTo(0);
     RuleFor(x => x.LineItemId).NotNull().NotEmpty();
     RuleSet("strict", () =>
     {
         RuleFor(x => x).Custom((newPriceRequest, context) =>
         {
             var lineItem = cartAggr.Cart.Items.FirstOrDefault(x => x.Id == newPriceRequest.LineItemId);
             if (lineItem != null)
             {
                 var newSalePrice = newPriceRequest.NewPrice;
                 if (lineItem.SalePrice > newSalePrice)
                 {
                     context.AddFailure(CartErrorDescriber.UnableToSetLessPrice(lineItem));
                 }
             }
         });
     });
 }
        public async Task ValidateItemQtyAdjustment_LineItemNotFound_Invalid()
        {
            // Arrange
            var item = _fixture.Create <ItemQtyAdjustment>();

            item.LineItem = null;
            var validator = new ItemQtyAdjustmentValidator();

            // Act
            var result = await validator.ValidateAsync(item);

            var expected = CartErrorDescriber.LineItemWithGivenIdNotFound(new LineItem
            {
                Id = item.LineItemId
            });

            // Assert
            result.Errors.Should().Contain(x =>
                                           x.ErrorMessage == expected.ErrorMessage &&
                                           x.ErrorCode == expected.ErrorCode);
        }
コード例 #11
0
        public CartLineItemValidator()
        {
            RuleFor(x => x).Custom((lineItemContext, context) =>
            {
                var lineItem        = lineItemContext.LineItem;
                var allCartProducts = lineItemContext.AllCartProducts;

                var cartProduct = allCartProducts.FirstOrDefault(x => x.Id.EqualsInvariant(lineItem.ProductId));
                if (cartProduct == null || !AbstractTypeFactory <ProductIsBuyableSpecification> .TryCreateInstance().IsSatisfiedBy(cartProduct))
                {
                    context.AddFailure(CartErrorDescriber.ProductUnavailableError(lineItem));
                }
                else
                {
                    var isProductAvailable = AbstractTypeFactory <ProductIsAvailableSpecification> .TryCreateInstance().IsSatisfiedBy(cartProduct, lineItem.Quantity);
                    if (!isProductAvailable)
                    {
                        context.AddFailure(CartErrorDescriber.ProductQtyChangedError(lineItem, cartProduct.AvailableQuantity));
                    }

                    var tierPrice = cartProduct.Price.GetTierPrice(lineItem.Quantity);
                    if (tierPrice.Price.Amount != lineItem.SalePrice)
                    {
                        context.AddFailure(CartErrorDescriber.ProductPriceChangedError(lineItem, lineItem.SalePrice, lineItem.SalePriceWithTax, tierPrice.Price.Amount, tierPrice.PriceWithTax.Amount));
                    }

                    var minQuantity = cartProduct?.Product?.MinQuantity;
                    if (lineItem.Quantity < minQuantity)
                    {
                        context.AddFailure(CartErrorDescriber.ProductMinQuantityError(lineItem, lineItem.Quantity, minQuantity ?? 0));
                    }

                    var maxQuantity = cartProduct?.Product?.MaxQuantity;
                    if (maxQuantity > 0 && lineItem.Quantity > maxQuantity)
                    {
                        context.AddFailure(CartErrorDescriber.ProductMaxQuantityError(lineItem, lineItem.Quantity, maxQuantity ?? 0));
                    }
                }
            });
        }
コード例 #12
0
 public CartShipmentValidator()
 {
     //To support the use case for partial shipment update when user sets the address first.
     //RuleFor(x => x.ShipmentMethodCode).NotNull().NotEmpty();
     RuleFor(x => x).Custom((shipmentContext, context) =>
     {
         var availShippingRates = shipmentContext.AvailShippingRates;
         var shipment           = shipmentContext.Shipment;
         if (availShippingRates != null && !string.IsNullOrEmpty(shipment.ShipmentMethodCode))
         {
             var shipmentShippingMethod = availShippingRates.FirstOrDefault(sm => shipment.ShipmentMethodCode.EqualsInvariant(sm.ShippingMethod.Code) && shipment.ShipmentMethodOption.EqualsInvariant(sm.OptionName));
             if (shipmentShippingMethod == null)
             {
                 context.AddFailure(CartErrorDescriber.ShipmentMethodUnavailable(shipment, shipment.ShipmentMethodCode, shipment.ShipmentMethodOption));
             }
             else if (shipmentShippingMethod.Rate != shipment.Price)
             {
                 context.AddFailure(CartErrorDescriber.ShipmentMethodPriceChanged(shipment, shipment.Price, shipment.PriceWithTax, shipmentShippingMethod.Rate, shipmentShippingMethod.RateWithTax));
             }
         }
     });
 }
        public async Task ValidateItemQtyAdjustment_LineItemNotFound_Invalid()
        {
            // Arrange
            var item      = _fixture.Create <ItemQtyAdjustment>();
            var aggregate = GetValidCartAggregate();

            aggregate.Cart.Items = Enumerable.Empty <LineItem>().ToList();
            var validator = new ItemQtyAdjustmentValidator(aggregate);

            // Act
            var result = await validator.ValidateAsync(item);

            var expected = CartErrorDescriber.LineItemWithGivenIdNotFound(new LineItem
            {
                Id = item.LineItemId
            });

            // Assert
            result.Errors.Should().Contain(x =>
                                           x.ErrorMessage == expected.ErrorMessage &&
                                           x.ErrorCode == expected.ErrorCode);
        }
コード例 #14
0
        public ItemQtyAdjustmentValidator()
        {
            RuleFor(x => x.NewQuantity).GreaterThan(0);
            RuleFor(x => x.LineItemId).NotNull();
            RuleFor(x => x.CartProduct).NotNull();
            RuleFor(x => x).Custom((qtyAdjust, context) =>
            {
                if (qtyAdjust.LineItem == null)
                {
                    context.AddFailure(CartErrorDescriber.LineItemWithGivenIdNotFound(new LineItem {
                        Id = qtyAdjust.LineItemId
                    }));
                }
                else if (qtyAdjust.LineItem.IsReadOnly || qtyAdjust.LineItem.IsGift)
                {
                    context.AddFailure(CartErrorDescriber.LineItemIsReadOnly(qtyAdjust.LineItem));
                }

                if (qtyAdjust.CartProduct != null && !new ProductIsAvailableSpecification().IsSatisfiedBy(qtyAdjust.CartProduct, qtyAdjust.NewQuantity))
                {
                    context.AddFailure(CartErrorDescriber.ProductQtyInsufficientError(qtyAdjust.CartProduct, qtyAdjust.NewQuantity, qtyAdjust.CartProduct.AvailableQuantity));
                }

                var minQuantity = qtyAdjust.CartProduct?.Product?.MinQuantity;
                if (qtyAdjust.NewQuantity < minQuantity)
                {
                    context.AddFailure(CartErrorDescriber.ProductMinQuantityError(qtyAdjust.CartProduct, qtyAdjust.NewQuantity, minQuantity ?? 0));
                }

                var maxQuantity = qtyAdjust.CartProduct?.Product?.MaxQuantity;
                if (maxQuantity > 0 && qtyAdjust.NewQuantity > maxQuantity)
                {
                    context.AddFailure(CartErrorDescriber.ProductMaxQuantityError(qtyAdjust.CartProduct, qtyAdjust.NewQuantity, maxQuantity ?? 0));
                }
            });
        }
コード例 #15
0
        public ChangeCartItemPriceValidator()
        {
            RuleFor(x => x.NewPrice).GreaterThanOrEqualTo(0);
            RuleFor(x => x.LineItemId).NotNull().NotEmpty();
            RuleSet("strict", () =>
            {
                RuleFor(x => x).Custom((newPriceRequest, context) =>
                {
                    if (newPriceRequest.LineItem != null)
                    {
                        if (newPriceRequest.LineItem.IsGift)
                        {
                            context.AddFailure(CartErrorDescriber.LineItemIsReadOnly(newPriceRequest.LineItem));
                        }

                        var newSalePrice = newPriceRequest.NewPrice;
                        if (newPriceRequest.LineItem.SalePrice > newSalePrice)
                        {
                            context.AddFailure(CartErrorDescriber.UnableToSetLessPrice(newPriceRequest.LineItem));
                        }
                    }
                });
            });
        }