public void Can_parse_allowed_quantities() { var pv = new ProductVariant() { AllowedQuantities = "1, 5,4,10,sdf" }; var result = pv.ParseAllowedQuatities(); result.Length.ShouldEqual(4); result[0].ShouldEqual(1); result[1].ShouldEqual(5); result[2].ShouldEqual(4); result[3].ShouldEqual(10); }
/// <summary> /// Validates a product variant for standard properties /// </summary> /// <param name="customer">Customer</param> /// <param name="shoppingCartType">Shopping cart type</param> /// <param name="productVariant">Product variant</param> /// <param name="selectedAttributes">Selected attributes</param> /// <param name="customerEnteredPrice">Customer entered price</param> /// <param name="quantity">Quantity</param> /// <returns>Warnings</returns> public virtual IList<string> GetStandardWarnings(Customer customer, ShoppingCartType shoppingCartType, ProductVariant productVariant, string selectedAttributes, decimal customerEnteredPrice, int quantity) { if (customer == null) throw new ArgumentNullException("customer"); if (productVariant == null) throw new ArgumentNullException("productVariant"); var warnings = new List<string>(); var product = productVariant.Product; if (product == null) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.CannotLoadProduct"), productVariant.ProductId)); return warnings; } //deleted? if (product.Deleted || productVariant.Deleted) { warnings.Add(_localizationService.GetResource("ShoppingCart.ProductDeleted")); return warnings; } //published? if (!product.Published || !productVariant.Published) { warnings.Add(_localizationService.GetResource("ShoppingCart.ProductUnpublished")); } //ACL if (!_aclService.Authorize(product, customer)) { warnings.Add(_localizationService.GetResource("ShoppingCart.ProductUnpublished")); } //disabled "add to cart" button if (shoppingCartType == ShoppingCartType.ShoppingCart && productVariant.DisableBuyButton) { warnings.Add(_localizationService.GetResource("ShoppingCart.BuyingDisabled")); } //disabled "add to wishlist" button if (shoppingCartType == ShoppingCartType.Wishlist && productVariant.DisableWishlistButton) { warnings.Add(_localizationService.GetResource("ShoppingCart.WishlistDisabled")); } //call for price if (shoppingCartType == ShoppingCartType.ShoppingCart && productVariant.CallForPrice) { warnings.Add(_localizationService.GetResource("Products.CallForPrice")); } //customer entered price if (productVariant.CustomerEntersPrice) { if (customerEnteredPrice < productVariant.MinimumCustomerEnteredPrice || customerEnteredPrice > productVariant.MaximumCustomerEnteredPrice) { decimal minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(productVariant.MinimumCustomerEnteredPrice, _workContext.WorkingCurrency); decimal maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(productVariant.MaximumCustomerEnteredPrice, _workContext.WorkingCurrency); warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.CustomerEnteredPrice.RangeError"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false))); } } //quantity validation var hasQtyWarnings = false; if (quantity < productVariant.OrderMinimumQuantity) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MinimumQuantity"), productVariant.OrderMinimumQuantity)); hasQtyWarnings = true; } if (quantity > productVariant.OrderMaximumQuantity) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MaximumQuantity"), productVariant.OrderMaximumQuantity)); hasQtyWarnings = true; } var allowedQuantities = productVariant.ParseAllowedQuatities(); if (allowedQuantities.Length > 0 && !allowedQuantities.Contains(quantity)) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.AllowedQuantities"), string.Join(", ", allowedQuantities))); } var validateOutOfStock = shoppingCartType == ShoppingCartType.ShoppingCart || !_shoppingCartSettings.AllowOutOfStockItemsToBeAddedToWishlist; if (validateOutOfStock && !hasQtyWarnings) { switch (productVariant.ManageInventoryMethod) { case ManageInventoryMethod.DontManageStock: { } break; case ManageInventoryMethod.ManageStock: { if ((BackorderMode)productVariant.BackorderMode == BackorderMode.NoBackorders) { if (productVariant.StockQuantity < quantity) { int maximumQuantityCanBeAdded = productVariant.StockQuantity; if (maximumQuantityCanBeAdded <= 0) warnings.Add(_localizationService.GetResource("ShoppingCart.OutOfStock")); else warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.QuantityExceedsStock"), maximumQuantityCanBeAdded)); } } } break; case ManageInventoryMethod.ManageStockByAttributes: { var combination = productVariant .ProductVariantAttributeCombinations .FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, selectedAttributes)); if (combination != null && !combination.AllowOutOfStockOrders && combination.StockQuantity < quantity) { int maximumQuantityCanBeAdded = combination.StockQuantity; if (maximumQuantityCanBeAdded <= 0) warnings.Add(_localizationService.GetResource("ShoppingCart.OutOfStock")); else warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.QuantityExceedsStock"), maximumQuantityCanBeAdded)); } } break; default: break; } } //availability dates bool availableStartDateError = false; if (productVariant.AvailableStartDateTimeUtc.HasValue) { DateTime now = DateTime.UtcNow; DateTime availableStartDateTime = DateTime.SpecifyKind(productVariant.AvailableStartDateTimeUtc.Value, DateTimeKind.Utc); if (availableStartDateTime.CompareTo(now) > 0) { warnings.Add(_localizationService.GetResource("ShoppingCart.NotAvailable")); availableStartDateError = true; } } if (productVariant.AvailableEndDateTimeUtc.HasValue && !availableStartDateError) { DateTime now = DateTime.UtcNow; DateTime availableEndDateTime = DateTime.SpecifyKind(productVariant.AvailableEndDateTimeUtc.Value, DateTimeKind.Utc); if (availableEndDateTime.CompareTo(now) < 0) { warnings.Add(_localizationService.GetResource("ShoppingCart.NotAvailable")); } } return warnings; }
protected ProductDetailsModel.ProductVariantModel PrepareProductVariantModel(ProductDetailsModel.ProductVariantModel model, ProductVariant productVariant) { if (productVariant == null) throw new ArgumentNullException("productVariant"); if (model == null) throw new ArgumentNullException("model"); #region Properties model.Id = productVariant.Id; model.Name = productVariant.GetLocalized(x => x.Name); model.ShowSku = _catalogSettings.ShowProductSku; model.Sku = productVariant.Sku; model.Description = productVariant.GetLocalized(x => x.Description); model.ShowManufacturerPartNumber = _catalogSettings.ShowManufacturerPartNumber; model.ManufacturerPartNumber = productVariant.ManufacturerPartNumber; model.ShowGtin = _catalogSettings.ShowGtin; model.Gtin = productVariant.Gtin; model.StockAvailablity = productVariant.FormatStockMessage(_localizationService); model.PictureModel.FullSizeImageUrl = _pictureService.GetPictureUrl(productVariant.PictureId, 0, false); model.PictureModel.ImageUrl = _pictureService.GetPictureUrl(productVariant.PictureId, _mediaSettings.ProductVariantPictureSize, false); model.PictureModel.Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name); model.PictureModel.AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name); model.HasSampleDownload = productVariant.IsDownload && productVariant.HasSampleDownload; model.IsCurrentCustomerRegistered = _workContext.CurrentCustomer.IsRegistered(); //back in stock subscriptions) if (productVariant.ManageInventoryMethod == ManageInventoryMethod.ManageStock && productVariant.BackorderMode == BackorderMode.NoBackorders && productVariant.AllowBackInStockSubscriptions && productVariant.StockQuantity <= 0) { //out of stock model.DisplayBackInStockSubscription = true; model.BackInStockAlreadySubscribed = _backInStockSubscriptionService.FindSubscription(_workContext.CurrentCustomer.Id, productVariant.Id) != null; } #endregion #region Product variant price model.ProductVariantPrice.ProductVariantId = productVariant.Id; model.ProductVariantPrice.DynamicPriceUpdate = _catalogSettings.EnableDynamicPriceUpdate; if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { model.ProductVariantPrice.HidePrices = false; if (productVariant.CustomerEntersPrice) { model.ProductVariantPrice.CustomerEntersPrice = true; } else { if (productVariant.CallForPrice) { model.ProductVariantPrice.CallForPrice = true; } else { decimal taxRate = decimal.Zero; decimal oldPriceBase = _taxService.GetProductPrice(productVariant, productVariant.OldPrice, out taxRate); decimal finalPriceWithoutDiscountBase = _taxService.GetProductPrice(productVariant, _priceCalculationService.GetFinalPrice(productVariant, false), out taxRate); decimal finalPriceWithDiscountBase = _taxService.GetProductPrice(productVariant, _priceCalculationService.GetFinalPrice(productVariant, true), out taxRate); decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency); decimal finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, _workContext.WorkingCurrency); decimal finalPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, _workContext.WorkingCurrency); if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero) model.ProductVariantPrice.OldPrice = _priceFormatter.FormatPrice(oldPrice); model.ProductVariantPrice.Price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase) model.ProductVariantPrice.PriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); model.ProductVariantPrice.PriceValue = finalPriceWithoutDiscount; model.ProductVariantPrice.PriceWithDiscountValue = finalPriceWithDiscount; } } } else { model.ProductVariantPrice.HidePrices = true; model.ProductVariantPrice.OldPrice = null; model.ProductVariantPrice.Price = null; } #endregion #region 'Add to cart' model model.AddToCart.ProductVariantId = productVariant.Id; //quantity model.AddToCart.EnteredQuantity = productVariant.OrderMinimumQuantity; //'add to cart', 'add to wishlist' buttons model.AddToCart.DisableBuyButton = productVariant.DisableBuyButton || !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart); model.AddToCart.DisableWishlistButton = productVariant.DisableWishlistButton || !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist); if (!_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { model.AddToCart.DisableBuyButton = true; model.AddToCart.DisableWishlistButton = true; } //pre-order model.AddToCart.AvailableForPreOrder = productVariant.AvailableForPreOrder; //customer entered price model.AddToCart.CustomerEntersPrice = productVariant.CustomerEntersPrice; if (model.AddToCart.CustomerEntersPrice) { decimal minimumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(productVariant.MinimumCustomerEnteredPrice, _workContext.WorkingCurrency); decimal maximumCustomerEnteredPrice = _currencyService.ConvertFromPrimaryStoreCurrency(productVariant.MaximumCustomerEnteredPrice, _workContext.WorkingCurrency); model.AddToCart.CustomerEnteredPrice = minimumCustomerEnteredPrice; model.AddToCart.CustomerEnteredPriceRange = string.Format(_localizationService.GetResource("Products.EnterProductPrice.Range"), _priceFormatter.FormatPrice(minimumCustomerEnteredPrice, false, false), _priceFormatter.FormatPrice(maximumCustomerEnteredPrice, false, false)); } var allowedQuantities = productVariant.ParseAllowedQuatities(); foreach (var qty in allowedQuantities) { model.AddToCart.AllowedQuantities.Add(new SelectListItem() { Text = qty.ToString(), Value = qty.ToString() }); } #endregion #region Gift card model.GiftCard.IsGiftCard = productVariant.IsGiftCard; if (model.GiftCard.IsGiftCard) { model.GiftCard.GiftCardType = productVariant.GiftCardType; model.GiftCard.SenderName = _workContext.CurrentCustomer.GetFullName(); model.GiftCard.SenderEmail = _workContext.CurrentCustomer.Email; } #endregion #region Product attributes var productVariantAttributes = _productAttributeService.GetProductVariantAttributesByProductVariantId(productVariant.Id); foreach (var attribute in productVariantAttributes) { var pvaModel = new ProductDetailsModel.ProductVariantModel.ProductVariantAttributeModel() { Id = attribute.Id, ProductVariantId = productVariant.Id, ProductAttributeId = attribute.ProductAttributeId, Name = attribute.ProductAttribute.GetLocalized(x => x.Name), Description = attribute.ProductAttribute.GetLocalized(x => x.Description), TextPrompt = attribute.TextPrompt, IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, AllowedFileExtensions = _catalogSettings.FileUploadAllowedExtensions, }; if (attribute.ShouldHaveValues()) { //values var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); foreach (var pvaValue in pvaValues) { var pvaValueModel = new ProductDetailsModel.ProductVariantModel.ProductVariantAttributeValueModel() { Id = pvaValue.Id, Name = pvaValue.GetLocalized(x=>x.Name), IsPreSelected = pvaValue.IsPreSelected, }; pvaModel.Values.Add(pvaValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal taxRate = decimal.Zero; decimal priceAdjustmentBase = _taxService.GetProductPrice(productVariant, pvaValue.PriceAdjustment, out taxRate); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment, false, false); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment, false, false); pvaValueModel.PriceAdjustmentValue = priceAdjustment; } } } model.ProductVariantAttributes.Add(pvaModel); } #endregion return model; }