/// <summary> /// Gets SKU, Manufacturer part number and GTIN /// </summary> /// <param name="product">Product</param> /// <param name="attributesXml">Attributes in XML format</param> /// <param name="productAttributeParser">Product attribute service (used when attributes are specified)</param> /// <param name="sku">SKU</param> /// <param name="manufacturerPartNumber">Manufacturer part number</param> /// <param name="gtin">GTIN</param> private static void GetSkuMpnGtin(this Product product, string attributesXml, IProductAttributeParser productAttributeParser, out string sku, out string manufacturerPartNumber, out string gtin) { if (product == null) { throw new ArgumentNullException("product"); } sku = null; manufacturerPartNumber = null; gtin = null; if (!String.IsNullOrEmpty(attributesXml) && product.ManageInventoryMethod == ManageInventoryMethod.ManageStockByAttributes) { //manage stock by attribute combinations if (productAttributeParser == null) { throw new ArgumentNullException("productAttributeParser"); } //let's find appropriate record var combination = product .ProductAttributeCombinations .FirstOrDefault(x => productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributesXml)); if (combination != null) { sku = combination.Sku; manufacturerPartNumber = combination.ManufacturerPartNumber; gtin = combination.Gtin; } } if (String.IsNullOrEmpty(sku)) { sku = product.Sku; } if (String.IsNullOrEmpty(manufacturerPartNumber)) { manufacturerPartNumber = product.ManufacturerPartNumber; } if (String.IsNullOrEmpty(gtin)) { gtin = product.Gtin; } }
public static ProductVariantAttributeCombination MergeWithCombination(this Product product, string selectedAttributes, IProductAttributeParser productAttributeParser) { Guard.ArgumentNotNull(productAttributeParser, "productAttributeParser"); if (selectedAttributes.IsNullOrEmpty()) return null; // let's find appropriate record var combination = product .ProductVariantAttributeCombinations .Where(x => x.IsActive == true) .FirstOrDefault(x => productAttributeParser.AreProductAttributesEqual(x.AttributesXml, selectedAttributes)); if (combination != null) { product.MergeWithCombination(combination); } return combination; }
public static ProductVariantAttributeCombination MergeWithCombination(this Product product, string selectedAttributes, IProductAttributeParser productAttributeParser) { Guard.ArgumentNotNull(productAttributeParser, "productAttributeParser"); if (selectedAttributes.IsNullOrEmpty()) { return(null); } // let's find appropriate record var combination = product .ProductVariantAttributeCombinations .Where(x => x.IsActive == true) .FirstOrDefault(x => productAttributeParser.AreProductAttributesEqual(x.AttributesXml, selectedAttributes)); if (combination != null) { product.MergeWithCombination(combination); } return(combination); }
protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationContext context, ProductBundleItemData bundleItem, IEnumerable <ProductBundleItemData> bundleItems) { var taxRate = decimal.Zero; var attributesTotalPriceBase = decimal.Zero; var preSelectedPriceAdjustmentBase = decimal.Zero; var isBundle = (product.ProductType == ProductType.BundledProduct); var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var selectedAttributes = new NameValueCollection(); var selectedAttributeValues = new List <ProductVariantAttributeValue>(); var attributes = context.Attributes.Load(product.Id); // 1. fill selectedAttributes with initially selected attributes foreach (var attribute in attributes.Where(x => x.ProductVariantAttributeValues.Count > 0 && x.ShouldHaveValues())) { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; var selectedValueIds = new List <int>(); var pvaValues = attribute.ProductVariantAttributeValues; foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (bundleItem.FilterOut(pvaValue, out attributeFilter)) { continue; } if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) { preSelectedValueId = attributeFilter.AttributeValueId; } if (!isBundlePricing && pvaValue.IsPreSelected) { decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); } } // value pre-selected by a bundle item filter discards the default pre-selection if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) { //defaultValue.IsPreSelected = true; selectedAttributeValues.Add(defaultValue); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } else { foreach (var value in pvaValues.Where(x => x.IsPreSelected)) { selectedAttributeValues.Add(value); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, value.Id, product.Id, bundleItemId); } } } // 2. find attribute combination for selected attributes and merge it if (!isBundle && selectedAttributes.Count > 0) { var attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List <string>(), true, bundleItemId); var combinations = context.AttributeCombinations.Load(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); if (selectedCombination != null && selectedCombination.IsActive && selectedCombination.Price.HasValue) { product.MergedDataValues = new Dictionary <string, object> { { "Price", selectedCombination.Price.Value } }; } } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues.Count > 0) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (bundleItem != null) { bundleItem.AdditionalCharge = attributesTotalPriceBase; } var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem, context); return(result); }
protected virtual decimal GetPreselectedPrice(Product product, ProductBundleItemData bundleItem, IList <ProductBundleItemData> bundleItems) { var taxRate = decimal.Zero; var attributesTotalPriceBase = decimal.Zero; var preSelectedPriceAdjustmentBase = decimal.Zero; var isBundle = (product.ProductType == ProductType.BundledProduct); var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var attributes = (isBundle ? new List <ProductVariantAttribute>() : _productAttributeService.GetProductVariantAttributesByProductId(product.Id)); var selectedAttributes = new NameValueCollection(); List <ProductVariantAttributeValue> selectedAttributeValues = null; foreach (var attribute in attributes) { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; if (attribute.ShouldHaveValues()) { var pvaValues = _productAttributeService.GetProductVariantAttributeValues(attribute.Id); if (pvaValues.Count == 0) { continue; } foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (bundleItem.FilterOut(pvaValue, out attributeFilter)) { continue; } if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) { preSelectedValueId = attributeFilter.AttributeValueId; } if (!isBundlePricing && pvaValue.IsPreSelected) { decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); } } // value pre-selected by a bundle item filter discards the default pre-selection if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) { defaultValue.IsPreSelected = true; } if (defaultValue == null) { defaultValue = pvaValues.FirstOrDefault(x => x.IsPreSelected); } if (defaultValue == null && attribute.IsRequired) { defaultValue = pvaValues.First(); } if (defaultValue != null) { selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } } } if (!isBundle && selectedAttributes.Count > 0) { string attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _commonServices.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List <string>(), true, bundleItemId); selectedAttributeValues = _productAttributeParser.ParseProductVariantAttributeValues(attributeXml).ToList(); var combinations = _productAttributeService.GetAllProductVariantAttributeCombinations(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); if (selectedCombination != null && selectedCombination.IsActive) { product.MergeWithCombination(selectedCombination); } } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues != null) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (bundleItem != null) { bundleItem.AdditionalCharge = attributesTotalPriceBase; } var result = GetFinalPrice(product, bundleItems, _commonServices.WorkContext.CurrentUser, attributesTotalPriceBase, true, 1, bundleItem); return(result); }
/// <summary> /// Gets SKU, Manufacturer part number and GTIN /// </summary> /// <param name="productVariant">Product variant</param> /// <param name="selectedAttributes">Selected attributes (XML format)</param> /// <param name="productAttributeParser">Product attribute service (used when attributes are specified)</param> /// <param name="sku">SKU</param> /// <param name="manufacturerPartNumber">Manufacturer part number</param> /// <param name="gtin">GTIN</param> private static void GetSkuMpnGtin(this ProductVariant productVariant, string selectedAttributes, IProductAttributeParser productAttributeParser, out string sku, out string manufacturerPartNumber, out string gtin) { if (productVariant == null) throw new ArgumentNullException("productVariant"); sku = null; manufacturerPartNumber = null; gtin = null; if (productVariant.ManageInventoryMethod == ManageInventoryMethod.ManageStockByAttributes) { //manage stock by attribute combinations if (productAttributeParser == null) throw new ArgumentNullException("productAttributeParser"); //let's find appropriate record var combination = productVariant .ProductVariantAttributeCombinations .FirstOrDefault(x => productAttributeParser.AreProductAttributesEqual(x.AttributesXml, selectedAttributes)); if (combination != null) { sku = combination.Sku; manufacturerPartNumber = combination.ManufacturerPartNumber; gtin = combination.Gtin; } } if (String.IsNullOrEmpty(sku)) sku = productVariant.Sku; if (String.IsNullOrEmpty(manufacturerPartNumber)) manufacturerPartNumber = productVariant.ManufacturerPartNumber; if (String.IsNullOrEmpty(gtin)) gtin = productVariant.Gtin; }
protected virtual decimal GetPreselectedPrice( Product product, Customer customer, Currency currency, PriceCalculationContext context, ProductBundleItemData bundleItem, IEnumerable <ProductBundleItemData> bundleItems) { var taxRate = decimal.Zero; var attributesTotalPriceBase = decimal.Zero; var preSelectedPriceAdjustmentBase = decimal.Zero; var isBundle = product.ProductType == ProductType.BundledProduct; var isBundleItemPricing = bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing; var isBundlePricing = bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing; var bundleItemId = bundleItem == null ? 0 : bundleItem.Item.Id; var query = new ProductVariantQuery(); var selectedAttributeValues = new List <ProductVariantAttributeValue>(); var attributes = context.Attributes.GetOrLoad(product.Id); // 1. Fill query with initially selected attributes. foreach (var attribute in attributes.Where(x => x.ProductVariantAttributeValues.Any() && x.ShouldHaveValues())) { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; var selectedValueIds = new List <int>(); var pvaValues = attribute.ProductVariantAttributeValues; foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (bundleItem?.Item?.FilterOut(pvaValue, out attributeFilter) ?? false) { continue; } if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) { preSelectedValueId = attributeFilter.AttributeValueId; } if (!isBundlePricing && pvaValue.IsPreSelected) { var includingTax = _services.WorkContext.TaxDisplayType == TaxDisplayType.IncludingTax; var attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue, product, customer, context, 1); var priceAdjustmentBase = _taxService.GetProductPrice(product, product.TaxCategoryId, attributeValuePriceAdjustment, includingTax, customer, currency, _taxSettings.PricesIncludeTax, out taxRate); preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); } } // Value pre-selected by a bundle item filter discards the default pre-selection. if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) { //defaultValue.IsPreSelected = true; selectedAttributeValues.Add(defaultValue); query.AddVariant(new ProductVariantQueryItem(defaultValue.Id.ToString()) { ProductId = product.Id, BundleItemId = bundleItemId, AttributeId = attribute.ProductAttributeId, VariantAttributeId = attribute.Id, Alias = attribute.ProductAttribute.Alias, ValueAlias = defaultValue.Alias }); } else { foreach (var value in pvaValues.Where(x => x.IsPreSelected)) { selectedAttributeValues.Add(value); query.AddVariant(new ProductVariantQueryItem(value.Id.ToString()) { ProductId = product.Id, BundleItemId = bundleItemId, AttributeId = attribute.ProductAttributeId, VariantAttributeId = attribute.Id, Alias = attribute.ProductAttribute.Alias, ValueAlias = value.Alias }); } } } // 2. Find attribute combination for selected attributes and merge it. if (!isBundle && query.Variants.Any()) { var attributeXml = query.CreateSelectedAttributesXml(product.Id, bundleItemId, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List <string>()); var combinations = context.AttributeCombinations.GetOrLoad(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); if (selectedCombination != null && selectedCombination.IsActive && selectedCombination.Price.HasValue) { product.MergedDataValues = new Dictionary <string, object> { { "Price", selectedCombination.Price.Value } }; if (selectedCombination.BasePriceAmount.HasValue) { product.MergedDataValues.Add("BasePriceAmount", selectedCombination.BasePriceAmount.Value); } if (selectedCombination.BasePriceBaseAmount.HasValue) { product.MergedDataValues.Add("BasePriceBaseAmount", selectedCombination.BasePriceBaseAmount.Value); } } } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues.Count > 0) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x, product, customer, context, 1)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (bundleItem != null) { bundleItem.AdditionalCharge = attributesTotalPriceBase; } var result = GetFinalPrice(product, bundleItems, customer, attributesTotalPriceBase, true, 1, bundleItem, context); return(result); }
/// <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); }
/// <summary> /// Validates shopping cart item /// </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> /// <param name="automaticallyAddRequiredProductVariantsIfEnabled">Automatically add required product variants if enabled</param> /// <returns>Warnings</returns> public virtual IList <string> GetShoppingCartItemWarnings(Customer customer, ShoppingCartType shoppingCartType, ProductVariant productVariant, string selectedAttributes, decimal customerEnteredPrice, int quantity, bool automaticallyAddRequiredProductVariantsIfEnabled) { if (productVariant == null) { throw new ArgumentNullException("productVariant"); } var warnings = new List <string>(); var product = productVariant.Product; if (product == null) { warnings.Add(string.Format("Product (Id={0}) can not be loaded", productVariant.ProductId)); return(warnings); } if (product.Deleted || productVariant.Deleted) { warnings.Add("Product is deleted"); return(warnings); } if (!product.Published || !productVariant.Published) { warnings.Add("Product is not published"); } if (shoppingCartType == ShoppingCartType.ShoppingCart && productVariant.DisableBuyButton) { warnings.Add("Buying is disabled for this product"); } if (shoppingCartType == ShoppingCartType.Wishlist && productVariant.DisableWishlistButton) { warnings.Add("Wishlist is disabled for this product"); } if (shoppingCartType == ShoppingCartType.ShoppingCart && productVariant.CallForPrice) { warnings.Add(_localizationService.GetResource("Products.CallForPrice")); } 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))); } } if (quantity < productVariant.OrderMinimumQuantity) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MinimumQuantity"), productVariant.OrderMinimumQuantity)); } if (quantity > productVariant.OrderMaximumQuantity) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.MaximumQuantity"), productVariant.OrderMaximumQuantity)); } 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 combinations = productVariant.ProductVariantAttributeCombinations; ProductVariantAttributeCombination combination = null; foreach (var comb1 in combinations) { if (_productAttributeParser.AreProductAttributesEqual(comb1.AttributesXml, selectedAttributes)) { combination = comb1; } } if (combination != null) { if (!combination.AllowOutOfStockOrders) { if (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("Product is not available"); 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("Product is not available"); } } //selected attributes warnings.AddRange(GetShoppingCartItemAttributeWarnings(shoppingCartType, productVariant, selectedAttributes)); //gift cards warnings.AddRange(GetShoppingCartItemGiftCardWarnings(shoppingCartType, productVariant, selectedAttributes)); //required product variants warnings.AddRange(GetRequiredProductVariantWarnings(customer, shoppingCartType, productVariant, automaticallyAddRequiredProductVariantsIfEnabled)); return(warnings); }
/// <summary> /// Finds a shopping cart item in the cart /// </summary> /// <param name="shoppingCart">Shopping cart</param> /// <param name="shoppingCartType">Shopping cart type</param> /// <param name="product">Product</param> /// <param name="attributes">Attributes</param> /// <param name="customerEnteredPrice">Price entered by a customer</param> /// <param name="rentalStartDate">Rental start date</param> /// <param name="rentalEndDate">Rental end date</param> /// <returns>Found shopping cart item</returns> public virtual async Task <ShoppingCartItem> FindShoppingCartItem(IList <ShoppingCartItem> shoppingCart, ShoppingCartType shoppingCartType, string productId, string warehouseId = null, IList <CustomAttribute> attributes = null, decimal?customerEnteredPrice = null, DateTime?rentalStartDate = null, DateTime?rentalEndDate = null) { if (shoppingCart == null) { throw new ArgumentNullException(nameof(shoppingCart)); } foreach (var sci in shoppingCart.Where(a => a.ShoppingCartTypeId == shoppingCartType)) { if (sci.ProductId == productId && sci.WarehouseId == warehouseId) { //attributes var _product = await _productService.GetProductById(sci.ProductId); bool attributesEqual = _productAttributeParser.AreProductAttributesEqual(_product, sci.Attributes, attributes, false); if (_product.ProductTypeId == ProductType.BundledProduct) { foreach (var bundle in _product.BundleProducts) { var p1 = await _productService.GetProductById(bundle.ProductId); if (p1 != null) { if (!_productAttributeParser.AreProductAttributesEqual(p1, sci.Attributes, attributes, false)) { attributesEqual = false; } } } } //gift vouchers bool giftVoucherInfoSame = true; if (_product.IsGiftVoucher) { _productAttributeParser.GetGiftVoucherAttribute(attributes, out var giftVoucherRecipientName1, out var giftVoucherRecipientEmail1, out var giftVoucherSenderName1, out var giftVoucherSenderEmail1, out var giftVoucherMessage1); _productAttributeParser.GetGiftVoucherAttribute(sci.Attributes, out var giftVoucherRecipientName2, out var giftVoucherRecipientEmail2, out var giftVoucherSenderName2, out var giftVoucherSenderEmail2, out var giftVoucherMessage2); if (giftVoucherRecipientName1.ToLowerInvariant() != giftVoucherRecipientName2.ToLowerInvariant() || giftVoucherSenderName1.ToLowerInvariant() != giftVoucherSenderName2.ToLowerInvariant()) { giftVoucherInfoSame = false; } } //price is the same (for products which require customers to enter a price) bool customerEnteredPricesEqual = true; if (sci.EnteredPrice.HasValue) { if (customerEnteredPrice.HasValue) { customerEnteredPricesEqual = Math.Round(sci.EnteredPrice.Value, 2) == Math.Round(customerEnteredPrice.Value, 2); } else { customerEnteredPricesEqual = false; } } else { if (customerEnteredPrice.HasValue) { customerEnteredPricesEqual = false; } } //found? if (attributesEqual && giftVoucherInfoSame && customerEnteredPricesEqual) { return(sci); } } } return(null); }