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)); } }); }
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); }
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); }
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); }
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); }
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)); } } }); }
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); }
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)); } }); }
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)); } } }); }); }