/// <summary> /// Creates a new context instance for given <paramref name="cartItem"/> and <paramref name="options"/>. /// </summary> /// <param name="cartItem">Shopping cart item.</param> /// <param name="options">The calculation options.</param> public PriceCalculationContext(OrganizedShoppingCartItem cartItem, PriceCalculationOptions options) : this(cartItem?.Item?.Product, cartItem?.Item?.Quantity ?? 1, options) { Guard.NotNull(cartItem, nameof(cartItem)); CartItem = cartItem; }
/// <summary> /// Gets discount amount /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(OrganizedShoppingCartItem shoppingCartItem, out Discount appliedDiscount) { appliedDiscount = null; var customer = shoppingCartItem.Item.Customer; var totalDiscountAmount = decimal.Zero; var product = shoppingCartItem.Item.Product; var quantity = shoppingCartItem.Item.Quantity; if (product != null) { var attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml).ToList(); foreach (var pvaValue in pvaValues) { attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue, product, customer, null, quantity); } var productDiscountAmount = GetDiscountAmount(product, customer, attributesTotalPrice, quantity, out appliedDiscount); totalDiscountAmount = productDiscountAmount * quantity; } totalDiscountAmount = totalDiscountAmount.RoundIfEnabledFor(_services.WorkContext.WorkingCurrency); return(totalDiscountAmount); }
public void Can_get_shopping_cart_item_subTotal() { //customer var customer = new Customer(); //shopping cart var product1 = new Product { Id = 1, Name = "Product name 1", Price = 12.34M, CustomerEntersPrice = false, Published = true, }; var sci1 = new ShoppingCartItem() { Customer = customer, CustomerId = customer.Id, Product = product1, ProductId = product1.Id, Quantity = 2, }; var item = new OrganizedShoppingCartItem(sci1); _priceCalcService.GetSubTotal(item, false).ShouldEqual(24.68); }
/// <summary> /// Gets discount amount /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="appliedDiscount">Applied discount</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(OrganizedShoppingCartItem shoppingCartItem, out Discount appliedDiscount) { var customer = shoppingCartItem.Item.Customer; appliedDiscount = null; decimal totalDiscountAmount = decimal.Zero; var product = shoppingCartItem.Item.Product; if (product != null) { decimal attributesTotalPrice = decimal.Zero; var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml).ToList(); foreach (var pvaValue in pvaValues) { attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue); } decimal productDiscountAmount = GetDiscountAmount(product, customer, attributesTotalPrice, shoppingCartItem.Item.Quantity, out appliedDiscount); totalDiscountAmount = productDiscountAmount * shoppingCartItem.Item.Quantity; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { totalDiscountAmount = Math.Round(totalDiscountAmount, 2); } return(totalDiscountAmount); }
/// <summary> /// Gets the shopping cart unit price (one item) /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart unit price (one item)</returns> public virtual decimal GetUnitPrice(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts) { decimal finalPrice = decimal.Zero; var customer = shoppingCartItem.Item.Customer; var product = shoppingCartItem.Item.Product; if (product != null) { if (product.CustomerEntersPrice) { finalPrice = shoppingCartItem.Item.CustomerEnteredPrice; } else if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { if (shoppingCartItem.ChildItems != null) { foreach (var bundleItem in shoppingCartItem.ChildItems) { bundleItem.Item.Product.MergeWithCombination(bundleItem.Item.AttributesXml, _productAttributeParser); } var bundleItems = shoppingCartItem.ChildItems.Where(x => x.BundleItemData.IsValid()).Select(x => x.BundleItemData).ToList(); finalPrice = GetFinalPrice(product, bundleItems, customer, decimal.Zero, includeDiscounts, shoppingCartItem.Item.Quantity); } } else { product.MergeWithCombination(shoppingCartItem.Item.AttributesXml, _productAttributeParser); var attributesTotalPrice = decimal.Zero; var pvaValuesEnum = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml); if (pvaValuesEnum != null) { var pvaValues = pvaValuesEnum.ToList(); foreach (var pvaValue in pvaValues) { attributesTotalPrice += GetProductVariantAttributeValuePriceAdjustment(pvaValue); } } finalPrice = GetFinalPrice(product, customer, attributesTotalPrice, includeDiscounts, shoppingCartItem.Item.Quantity, shoppingCartItem.BundleItemData); } } if (_shoppingCartSettings.RoundPricesDuringCalculation) { finalPrice = Math.Round(finalPrice, 2); } return(finalPrice); }
public virtual async Task <Money> GetUnitPriceAsync(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts) { Guard.NotNull(shoppingCartItem, nameof(shoppingCartItem)); var currency = _workContext.WorkingCurrency; var cartItem = shoppingCartItem.Item; var customer = cartItem.Customer; var product = cartItem.Product; if (product != null) { if (product.CustomerEntersPrice) { return(currency.AsMoney(cartItem.CustomerEnteredPrice)); } else if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { if (shoppingCartItem.ChildItems != null) { foreach (var bundleItem in shoppingCartItem.ChildItems) { await _productAttributeMaterializer.MergeWithCombinationAsync(bundleItem.Item.Product, bundleItem.Item.AttributeSelection); } var bundleItems = shoppingCartItem.ChildItems .Where(x => x.BundleItemData?.Item != null) .Select(x => x.BundleItemData); var finalPrice = await GetFinalPriceAsync(product, bundleItems, null, customer, includeDiscounts, cartItem.Quantity); return(currency.AsMoney(finalPrice.Amount)); } } else { await _productAttributeMaterializer.MergeWithCombinationAsync(product, cartItem.AttributeSelection); var pvaValues = await _productAttributeMaterializer.MaterializeProductVariantAttributeValuesAsync(cartItem.AttributeSelection); var attributesTotalPrice = new Money(currency); foreach (var pvaValue in pvaValues) { attributesTotalPrice += await GetProductVariantAttributeValuePriceAdjustmentAsync(pvaValue, product, customer, null, cartItem.Quantity); } var finalPrice = await GetFinalPriceAsync(product, attributesTotalPrice, customer, includeDiscounts, cartItem.Quantity, shoppingCartItem.BundleItemData); return(currency.AsMoney(finalPrice.Amount)); } } return(new Money(currency)); }
/// <summary> /// Gets shopping cart item total weight /// </summary> /// <param name="shoppingCartItem">Shopping cart item</param> /// <returns>Shopping cart item weight</returns> public virtual decimal GetShoppingCartItemTotalWeight(OrganizedShoppingCartItem shoppingCartItem) { if (shoppingCartItem == null) { throw new ArgumentNullException("shoppingCartItem"); } decimal totalWeight = GetShoppingCartItemWeight(shoppingCartItem) * shoppingCartItem.Item.Quantity; return(totalWeight); }
public override async Task MapAsync(OrganizedShoppingCartItem from, ShoppingCartModel.ShoppingCartItemModel to, dynamic parameters = null) { Guard.NotNull(from, nameof(from)); Guard.NotNull(to, nameof(to)); var item = from.Item; var product = item.Product; await base.MapAsync(from, to, (object)parameters); to.Weight = product.Weight; to.IsShipEnabled = product.IsShippingEnabled; to.IsDownload = product.IsDownload; to.HasUserAgreement = product.HasUserAgreement; to.IsEsd = product.IsEsd; to.DisableWishlistButton = product.DisableWishlistButton; if (product.DisplayDeliveryTimeAccordingToStock(_catalogSettings)) { var deliveryTime = await _deliveryTimeService.GetDeliveryTimeAsync(product.GetDeliveryTimeIdAccordingToStock(_catalogSettings)); if (deliveryTime != null) { to.DeliveryTimeName = deliveryTime.GetLocalized(x => x.Name); to.DeliveryTimeHexValue = deliveryTime.ColorHexValue; if (_shoppingCartSettings.DeliveryTimesInShoppingCart is DeliveryTimesPresentation.DateOnly or DeliveryTimesPresentation.LabelAndDate) { to.DeliveryTimeDate = _deliveryTimeService.GetFormattedDeliveryDate(deliveryTime); } } } if (from.Item.BundleItem == null) { var selectedValues = await _productAttributeMaterializer.MaterializeProductVariantAttributeValuesAsync(item.AttributeSelection); selectedValues.Each(x => to.Weight += x.WeightAdjustment); } if (from.ChildItems != null) { foreach (var childItem in from.ChildItems.Where(x => x.Item.Id != item.Id)) { var model = new ShoppingCartModel.ShoppingCartItemModel(); await childItem.MapAsync(model, (object)parameters); to.AddChildItems(model); } } }
public virtual async Task <decimal> GetUnitPriceAsync(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts) { Guard.NotNull(shoppingCartItem, nameof(shoppingCartItem)); var finalPrice = decimal.Zero; var customer = shoppingCartItem.Item.Customer; var product = shoppingCartItem.Item.Product; if (product != null) { if (product.CustomerEntersPrice) { finalPrice = shoppingCartItem.Item.CustomerEnteredPrice; } else if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { if (shoppingCartItem.ChildItems != null) { foreach (var bundleItem in shoppingCartItem.ChildItems) { await _productAttributeMaterializer.MergeWithCombinationAsync(bundleItem.Item.Product, bundleItem.Item.AttributeSelection); } var bundleItems = shoppingCartItem.ChildItems .Where(x => x.BundleItemData?.Item != null) .Select(x => x.BundleItemData) .ToList(); finalPrice = await GetFinalPriceAsync(product, bundleItems, customer, decimal.Zero, includeDiscounts, shoppingCartItem.Item.Quantity); } } else { await _productAttributeMaterializer.MergeWithCombinationAsync(product, shoppingCartItem.Item.AttributeSelection); var attributesTotalPrice = decimal.Zero; var pvaValues = await _productAttributeMaterializer.MaterializeProductVariantAttributeValuesAsync(shoppingCartItem.Item.AttributeSelection); foreach (var pvaValue in pvaValues) { attributesTotalPrice += await GetProductVariantAttributeValuePriceAdjustmentAsync(pvaValue, product, customer, null, shoppingCartItem.Item.Quantity); } finalPrice = await GetFinalPriceAsync(product, customer, attributesTotalPrice, includeDiscounts, shoppingCartItem.Item.Quantity, shoppingCartItem.BundleItemData); } } finalPrice = _workContext.WorkingCurrency.RoundIfEnabledFor(finalPrice); return(finalPrice); }
public static async Task MapAsync(this OrganizedShoppingCartItem entity, ImageModel model, int pictureSize, string productName) { Guard.NotNull(entity, nameof(entity)); Guard.NotNull(model, nameof(model)); var product = entity.Item.Product; dynamic parameters = new ExpandoObject(); parameters.Selection = entity.Item.AttributeSelection; parameters.Product = product; parameters.ProductName = productName.HasValue() ? productName : product.GetLocalized(x => x.Name); parameters.PictureSize = pictureSize; await MapperFactory.MapAsync(entity, model, parameters); }
public static IList <OrganizedShoppingCartItem> Organize(this IList <ShoppingCartItem> cart) { var result = new List <OrganizedShoppingCartItem>(); var productAttributeParser = EngineContext.Current.Resolve <IProductAttributeParser>(); if (cart == null || cart.Count <= 0) { return(result); } foreach (var parent in cart.Where(x => x.ParentItemId == null)) { var parentItem = new OrganizedShoppingCartItem(parent); var childs = cart.Where(x => x.ParentItemId != null && x.ParentItemId == parent.Id && x.Id != parent.Id && x.ShoppingCartTypeId == parent.ShoppingCartTypeId && x.Product.CanBeBundleItem()); foreach (var child in childs) { var childItem = new OrganizedShoppingCartItem(child); if (parent.Product != null && parent.Product.BundlePerItemPricing && child.AttributesXml != null && child.BundleItem != null) { var combination = productAttributeParser.FindProductVariantAttributeCombination(child.Product, child.AttributesXml); if (combination != null && combination.Price.HasValue) { childItem.BundleItemData.PriceOverride = combination.Price.Value; } else { var attributeValues = productAttributeParser.ParseProductVariantAttributeValues(child.AttributesXml); if (attributeValues != null) { childItem.BundleItemData.AdditionalCharge = decimal.Zero; attributeValues.Each(x => childItem.BundleItemData.AdditionalCharge += x.PriceAdjustment); } } } parentItem.ChildItems.Add(childItem); } result.Add(parentItem); } return(result); }
/// <summary> /// Calculates the unit price for a given shopping cart item. /// </summary> /// <param name="priceCalculationService">Price calculation service.</param> /// <param name="cartItem">Shopping cart item.</param> /// <param name="ignoreDiscounts">A value indicating whether to ignore discounts.</param> /// <param name="targetCurrency">The target currency to use for money conversion. Obtained from <see cref="IWorkContext.WorkingCurrency"/> if <c>null</c>.</param> /// <returns>Calculated unit price.</returns> public static async Task <CalculatedPrice> CalculateUnitPriceAsync( this IPriceCalculationService2 priceCalculationService, OrganizedShoppingCartItem cartItem, bool ignoreDiscounts = false, Currency targetCurrency = null) { Guard.NotNull(priceCalculationService, nameof(priceCalculationService)); Guard.NotNull(cartItem, nameof(cartItem)); var options = priceCalculationService.CreateDefaultOptions(false, cartItem.Item.Customer, targetCurrency); options.IgnoreDiscounts = ignoreDiscounts; var context = new PriceCalculationContext(cartItem, options); return(await priceCalculationService.CalculatePriceAsync(context)); }
public virtual async Task <decimal> GetCartItemWeightAsync(OrganizedShoppingCartItem cartItem, bool multipliedByQuantity = true) { Guard.NotNull(cartItem, nameof(cartItem)); if (cartItem.Item.Product is null) { return(decimal.Zero); } var attributesWeight = cartItem.Item.RawAttributes.HasValue() ? await GetCartItemsAttributesWeightAsync(new List <OrganizedShoppingCartItem> { cartItem }, false) : decimal.Zero; return(multipliedByQuantity ? (cartItem.Item.Product.Weight + attributesWeight) * cartItem.Item.Quantity : cartItem.Item.Product.Weight + attributesWeight); }
public void Can_get_shoppingCartItem_totalWeight_without_attributes() { var sci = new ShoppingCartItem() { AttributesXml = "", Quantity = 3, Product = new Product() { Weight = 1.5M, Height = 2.5M, Length = 3.5M, Width = 4.5M } }; var item = new OrganizedShoppingCartItem(sci); _shippingService.GetShoppingCartItemTotalWeight(item).ShouldEqual(4.5M); }
public override async Task MapAsync(OrganizedShoppingCartItem from, WishlistModel.WishlistItemModel to, dynamic parameters = null) { Guard.NotNull(from, nameof(from)); Guard.NotNull(to, nameof(to)); await base.MapAsync(from, to); if (from.ChildItems != null) { foreach (var childItem in from.ChildItems.Where(x => x.Item.Id != from.Item.Id)) { var model = new WishlistModel.WishlistItemModel { DisableBuyButton = childItem.Item.Product.DisableBuyButton }; await childItem.MapAsync(model); to.AddChildItems(model); } } }
/// <summary> /// Gets shopping cart item weight (of one item) /// </summary> /// <param name="shoppingCartItem">Shopping cart item</param> /// <returns>Shopping cart item weight</returns> public virtual decimal GetShoppingCartItemWeight(OrganizedShoppingCartItem shoppingCartItem) { if (shoppingCartItem == null) { throw new ArgumentNullException("shoppingCartItem"); } decimal weight = decimal.Zero; if (shoppingCartItem.Item.Product != null) { decimal attributesTotalWeight = decimal.Zero; if (!String.IsNullOrEmpty(shoppingCartItem.Item.AttributesXml)) { var pvaValues = _productAttributeParser.ParseProductVariantAttributeValues(shoppingCartItem.Item.AttributesXml); foreach (var pvaValue in pvaValues) { if (pvaValue.ValueType == ProductVariantAttributeValueType.ProductLinkage) { var linkedProduct = _productService.GetProductById(pvaValue.LinkedProductId); if (linkedProduct != null && linkedProduct.IsShipEnabled) { attributesTotalWeight += (linkedProduct.Weight * pvaValue.Quantity); } } else { attributesTotalWeight += pvaValue.WeightAdjustment; } } } weight = shoppingCartItem.Item.Product.Weight + attributesTotalWeight; } return(weight); }
public virtual AdjustInventoryResult AdjustInventory(OrganizedShoppingCartItem sci, bool decrease) { if (sci == null) { throw new ArgumentNullException("cartItem"); } if (sci.Item.Product.ProductType == ProductType.BundledProduct && sci.Item.Product.BundlePerItemShoppingCart) { if (sci.ChildItems != null) { foreach (var child in sci.ChildItems.Where(x => x.Item.Id != sci.Item.Id)) { AdjustInventory(child.Item.Product, decrease, sci.Item.Quantity * child.Item.Quantity, child.Item.AttributesXml); } } return(new AdjustInventoryResult()); } else { return(AdjustInventory(sci.Item.Product, decrease, sci.Item.Quantity, sci.Item.AttributesXml)); } }
/// <summary> /// Creates a product URL including variant query string. /// </summary> /// <param name="helper">Product URL helper</param> /// <param name="productSeName">Product SEO name</param> /// <param name="cartItem">Organized shopping cart item</param> /// <returns>Product URL</returns> public static string GetProductUrl( this ProductUrlHelper helper, string productSeName, OrganizedShoppingCartItem cartItem) { Guard.NotNull(cartItem, nameof(cartItem)); var query = new ProductVariantQuery(); var product = cartItem.Item.Product; if (product.ProductType != ProductType.BundledProduct) { helper.DeserializeQuery(query, product.Id, cartItem.Item.AttributesXml); } else if (cartItem.ChildItems != null && product.BundlePerItemPricing) { foreach (var childItem in cartItem.ChildItems.Where(x => x.Item.Id != cartItem.Item.Id)) { helper.DeserializeQuery(query, childItem.Item.ProductId, childItem.Item.AttributesXml, childItem.BundleItemData.Item.Id); } } return(helper.GetProductUrl(query, productSeName)); }
/// <summary> /// Creates a product URL including variant query string. /// </summary> /// <param name="helper">Product URL helper.</param> /// <param name="productSlug">Product URL slug.</param> /// <param name="cartItem">Organized shopping cart item.</param> /// <returns>Product URL.</returns> public static async Task <string> GetProductUrlAsync(this ProductUrlHelper helper, string productSlug, OrganizedShoppingCartItem cartItem) { Guard.NotNull(helper, nameof(helper)); Guard.NotNull(cartItem, nameof(cartItem)); var query = new ProductVariantQuery(); var product = cartItem.Item.Product; if (product.ProductType != ProductType.BundledProduct) { await helper.AddAttributesToQueryAsync(query, cartItem.Item.AttributeSelection, product.Id); } else if (cartItem.ChildItems != null && product.BundlePerItemPricing) { foreach (var childItem in cartItem.ChildItems.Where(x => x.Item.Id != cartItem.Item.Id)) { await helper.AddAttributesToQueryAsync(query, childItem.Item.AttributeSelection, childItem.Item.ProductId, childItem.Item.BundleItem.Id); } } return(helper.GetProductUrl(productSlug, query)); }
/// <summary> /// Gets discount amount /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <returns>Discount amount</returns> public virtual decimal GetDiscountAmount(OrganizedShoppingCartItem shoppingCartItem) { Discount appliedDiscount; return(GetDiscountAmount(shoppingCartItem, out appliedDiscount)); }
/// <summary> /// Gets the shopping cart item sub total /// </summary> /// <param name="shoppingCartItem">The shopping cart item</param> /// <param name="includeDiscounts">A value indicating whether include discounts or not for price computation</param> /// <returns>Shopping cart item sub total</returns> public virtual decimal GetSubTotal(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts) { return(GetUnitPrice(shoppingCartItem, includeDiscounts) * shoppingCartItem.Item.Quantity); }
/// <summary> /// Adjusts product inventory. The caller is responsible for database commit. /// </summary> /// <param name="productService">Product service.</param> /// <param name="item">Shopping cart item.</param> /// <param name="decrease">A value indicating whether to increase or descrease product stock quantity.</param> /// <returns>Adjust inventory result.</returns> public static async Task <AdjustInventoryResult> AdjustInventoryAsync(this IProductService productService, OrganizedShoppingCartItem item, bool decrease) { Guard.NotNull(productService, nameof(productService)); Guard.NotNull(item, nameof(item)); if (item.Item.Product.ProductType == ProductType.BundledProduct && item.Item.Product.BundlePerItemShoppingCart) { if (item.ChildItems != null) { foreach (var child in item.ChildItems.Where(x => x.Item.Id != item.Item.Id)) { await productService.AdjustInventoryAsync( child.Item.Product, child.Item.AttributeSelection, decrease, item.Item.Quantity *child.Item.Quantity); } } return(new AdjustInventoryResult()); } else { return(await productService.AdjustInventoryAsync( item.Item.Product, item.Item.AttributeSelection, decrease, item.Item.Quantity)); } }
public virtual async Task <Money> GetSubTotalAsync(OrganizedShoppingCartItem shoppingCartItem, bool includeDiscounts) { return(_primaryCurrency.AsMoney(await GetUnitPriceAmountAsync(shoppingCartItem, includeDiscounts) * shoppingCartItem.Item.Quantity)); }
public virtual async Task <(Money Amount, Discount AppliedDiscount)> GetDiscountAmountAsync(OrganizedShoppingCartItem shoppingCartItem) { Guard.NotNull(shoppingCartItem, nameof(shoppingCartItem)); var customer = shoppingCartItem.Item.Customer; var product = shoppingCartItem.Item.Product; var quantity = shoppingCartItem.Item.Quantity; if (product == null) { return(new(_primaryCurrency), null); } var attributesTotalPrice = decimal.Zero; var pvaValues = await _productAttributeMaterializer.MaterializeProductVariantAttributeValuesAsync(shoppingCartItem.Item.AttributeSelection); foreach (var pvaValue in pvaValues) { attributesTotalPrice += await GetVariantPriceAdjustmentAsync(pvaValue, product, customer, null, quantity); } var(discountAmount, appliedDiscount) = await GetDiscountAmountAsync(product, attributesTotalPrice, customer, quantity); return(_primaryCurrency.AsMoney(discountAmount * quantity), appliedDiscount); }
protected override void Map(OrganizedShoppingCartItem from, WishlistModel.WishlistItemModel to, dynamic parameters = null) => throw new NotImplementedException();
private async Task <WishlistModel.ShoppingCartItemModel> PrepareWishlistCartItemModelAsync(OrganizedShoppingCartItem cartItem) { Guard.NotNull(cartItem, nameof(cartItem)); var item = cartItem.Item; var product = item.Product; var customer = item.Customer; var currency = Services.WorkContext.WorkingCurrency; await _productAttributeMaterializer.MergeWithCombinationAsync(product, item.AttributeSelection); var productSeName = await SeoExtensions.GetActiveSlugAsync(product); var model = new WishlistModel.ShoppingCartItemModel { Id = item.Id, Sku = product.Sku, ProductId = product.Id, ProductName = product.GetLocalized(x => x.Name), ProductSeName = productSeName, ProductUrl = await _productUrlHelper.GetProductUrlAsync(productSeName, cartItem), EnteredQuantity = item.Quantity, MinOrderAmount = product.OrderMinimumQuantity, MaxOrderAmount = product.OrderMaximumQuantity, QuantityStep = product.QuantityStep > 0 ? product.QuantityStep : 1, ShortDesc = product.GetLocalized(x => x.ShortDescription), ProductType = product.ProductType, VisibleIndividually = product.Visibility != ProductVisibility.Hidden, CreatedOnUtc = item.UpdatedOnUtc, DisableBuyButton = product.DisableBuyButton, }; if (item.BundleItem != null) { model.BundleItem.Id = item.BundleItem.Id; model.BundleItem.DisplayOrder = item.BundleItem.DisplayOrder; model.BundleItem.HideThumbnail = item.BundleItem.HideThumbnail; model.BundlePerItemPricing = item.BundleItem.BundleProduct.BundlePerItemPricing; model.BundlePerItemShoppingCart = item.BundleItem.BundleProduct.BundlePerItemShoppingCart; model.AttributeInfo = await _productAttributeFormatter.FormatAttributesAsync(item.AttributeSelection, product, customer, includePrices : false, includeGiftCardAttributes : false, includeHyperlinks : false); var bundleItemName = item.BundleItem.GetLocalized(x => x.Name); if (bundleItemName.HasValue()) { model.ProductName = bundleItemName; } var bundleItemShortDescription = item.BundleItem.GetLocalized(x => x.ShortDescription); if (bundleItemShortDescription.HasValue()) { model.ShortDesc = bundleItemShortDescription; } if (model.BundlePerItemPricing && model.BundlePerItemShoppingCart) { (var bundleItemPriceBase, var bundleItemTaxRate) = await _taxService.GetProductPriceAsync(product, await _priceCalculationService.GetSubTotalAsync(cartItem, true)); var bundleItemPrice = _currencyService.ConvertFromPrimaryCurrency(bundleItemPriceBase.Amount, currency); model.BundleItem.PriceWithDiscount = bundleItemPrice.ToString(); } } else { model.AttributeInfo = await _productAttributeFormatter.FormatAttributesAsync(item.AttributeSelection, product, customer); } var allowedQuantities = product.ParseAllowedQuantities(); foreach (var qty in allowedQuantities) { model.AllowedQuantities.Add(new SelectListItem { Text = qty.ToString(), Value = qty.ToString(), Selected = item.Quantity == qty }); } var quantityUnit = await _db.QuantityUnits.FindByIdAsync(product.QuantityUnitId ?? 0); if (quantityUnit != null) { model.QuantityUnitName = quantityUnit.GetLocalized(x => x.Name); } if (product.IsRecurring) { model.RecurringInfo = string.Format(T("ShoppingCart.RecurringPeriod"), product.RecurringCycleLength, product.RecurringCyclePeriod.GetLocalizedEnum()); } if (product.CallForPrice) { model.UnitPrice = T("Products.CallForPrice"); } else { var unitPriceWithDiscount = await _priceCalculationService.GetUnitPriceAsync(cartItem, true); var unitPriceBaseWithDiscount = await _taxService.GetProductPriceAsync(product, unitPriceWithDiscount); unitPriceWithDiscount = _currencyService.ConvertFromPrimaryCurrency(unitPriceBaseWithDiscount.Price.Amount, currency); model.UnitPrice = unitPriceWithDiscount.ToString(); } // Subtotal and discount. if (product.CallForPrice) { model.SubTotal = T("Products.CallForPrice"); } else { var cartItemSubTotalWithDiscount = await _priceCalculationService.GetSubTotalAsync(cartItem, true); var cartItemSubTotalWithDiscountBase = await _taxService.GetProductPriceAsync(product, cartItemSubTotalWithDiscount); cartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryCurrency(cartItemSubTotalWithDiscountBase.Price.Amount, currency); model.SubTotal = cartItemSubTotalWithDiscount.ToString(); // Display an applied discount amount. var cartItemSubTotalWithoutDiscount = await _priceCalculationService.GetSubTotalAsync(cartItem, false); var cartItemSubTotalWithoutDiscountBase = await _taxService.GetProductPriceAsync(product, cartItemSubTotalWithoutDiscount); var cartItemSubTotalDiscountBase = cartItemSubTotalWithoutDiscountBase.Price - cartItemSubTotalWithDiscountBase.Price; if (cartItemSubTotalDiscountBase > decimal.Zero) { var shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryCurrency(cartItemSubTotalDiscountBase.Amount, currency); model.Discount = shoppingCartItemDiscount.ToString(); } } if (item.BundleItem != null) { if (_shoppingCartSettings.ShowProductBundleImagesOnShoppingCart) { model.Image = await PrepareCartItemPictureModelAsync(product, _mediaSettings.CartThumbBundleItemPictureSize, model.ProductName, item.AttributeSelection); } } else { if (_shoppingCartSettings.ShowProductImagesOnShoppingCart) { model.Image = await PrepareCartItemPictureModelAsync(product, _mediaSettings.CartThumbPictureSize, model.ProductName, item.AttributeSelection); } } var itemWarnings = new List <string>(); var itemIsValid = await _shoppingCartValidator.ValidateCartAsync(new List <OrganizedShoppingCartItem> { cartItem }, itemWarnings); if (!itemIsValid) { model.Warnings.AddRange(itemWarnings); } if (cartItem.ChildItems != null) { foreach (var childItem in cartItem.ChildItems.Where(x => x.Item.Id != item.Id)) { var childModel = await PrepareWishlistCartItemModelAsync(childItem); model.ChildItems.Add(childModel); } } return(model); }
public static async Task MapAsync(this OrganizedShoppingCartItem entity, WishlistModel.WishlistItemModel model) { await MapperFactory.MapAsync(entity, model, null); }
public virtual async Task <PriceCalculationContext> CreateCalculationContextAsync(OrganizedShoppingCartItem cartItem, PriceCalculationOptions options) { Guard.NotNull(cartItem, nameof(cartItem)); Guard.NotNull(options, nameof(options)); var product = cartItem.Item.Product; var context = new PriceCalculationContext(product, cartItem.Item.Quantity, options) { CartItem = cartItem }; // Include attributes selected for this cart item in price calculation. context.AddSelectedAttributes(cartItem); // Include bundle item data if the cart item is a bundle item. if (cartItem.Item.BundleItem != null) { context.BundleItem = cartItem.Item.BundleItem; } // Perf: we already have the bundle items of a bundled product. No need to load them again during calculation. if (cartItem.ChildItems?.Any() ?? false) { context.BundleItems = cartItem.ChildItems .Where(x => x.Item.BundleItem != null) .Select(x => x.Item.BundleItem) .ToList(); } if (product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing) { Guard.NotNull(cartItem.ChildItems, nameof(cartItem.ChildItems)); foreach (var bundleItem in cartItem.ChildItems) { await _productAttributeMaterializer.MergeWithCombinationAsync(bundleItem.Item.Product, bundleItem.Item.AttributeSelection); } } else { await _productAttributeMaterializer.MergeWithCombinationAsync(product, cartItem.Item.AttributeSelection); } return(context); }
public override async Task MapAsync(OrganizedShoppingCartItem from, TModel to, dynamic parameters = null) { Guard.NotNull(from, nameof(from)); Guard.NotNull(to, nameof(to)); var item = from.Item; var product = from.Item.Product; var customer = item.Customer; var currency = _services.WorkContext.WorkingCurrency; var shoppingCartType = item.ShoppingCartType; var productSeName = await product.GetActiveSlugAsync(); var taxFormat = parameters?.TaxFormat as string; var batchContext = parameters?.BatchContext as ProductBatchContext; await _productAttributeMaterializer.MergeWithCombinationAsync(product, item.AttributeSelection); // General model data. to.Id = item.Id; to.Sku = product.Sku; to.ProductId = product.Id; to.ProductName = product.GetLocalized(x => x.Name); to.ProductSeName = productSeName; to.ProductUrl = await ProductUrlHelper.GetProductUrlAsync(productSeName, from); to.EnteredQuantity = item.Quantity; to.MinOrderAmount = product.OrderMinimumQuantity; to.MaxOrderAmount = product.OrderMaximumQuantity; to.QuantityStep = product.QuantityStep > 0 ? product.QuantityStep : 1; to.ShortDesc = product.GetLocalized(x => x.ShortDescription); to.ProductType = product.ProductType; to.VisibleIndividually = product.Visibility != ProductVisibility.Hidden; to.CreatedOnUtc = item.UpdatedOnUtc; if (item.BundleItem != null) { to.BundleItem.Id = item.BundleItem.Id; to.BundleItem.DisplayOrder = item.BundleItem.DisplayOrder; to.BundleItem.HideThumbnail = item.BundleItem.HideThumbnail; to.BundlePerItemPricing = item.BundleItem.BundleProduct.BundlePerItemPricing; to.BundlePerItemShoppingCart = item.BundleItem.BundleProduct.BundlePerItemShoppingCart; to.AttributeInfo = await ProductAttributeFormatter.FormatAttributesAsync( item.AttributeSelection, product, customer, includePrices : false, includeGiftCardAttributes : true, includeHyperlinks : true, batchContext : batchContext); var bundleItemName = item.BundleItem.GetLocalized(x => x.Name); if (bundleItemName.Value.HasValue()) { to.ProductName = bundleItemName; } var bundleItemShortDescription = item.BundleItem.GetLocalized(x => x.ShortDescription); if (bundleItemShortDescription.Value.HasValue()) { to.ShortDesc = bundleItemShortDescription; } var calculationOptions = _priceCalculationService.CreateDefaultOptions(false, customer, null, batchContext); var calculationContext = await _priceCalculationService.CreateCalculationContextAsync(from, calculationOptions); var(bundleItemUnitPrice, bundleItemSubtotal) = await _priceCalculationService.CalculateSubtotalAsync(calculationContext); if (to.BundlePerItemPricing && to.BundlePerItemShoppingCart) { to.BundleItem.PriceWithDiscount = bundleItemSubtotal.FinalPrice.ToString(); } to.BasePrice = _priceCalculationService.GetBasePriceInfo(product, bundleItemUnitPrice.FinalPrice); } else { to.AttributeInfo = await ProductAttributeFormatter.FormatAttributesAsync(item.AttributeSelection, product, customer, batchContext : batchContext); } var allowedQuantities = product.ParseAllowedQuantities(); foreach (var quantity in allowedQuantities) { to.AllowedQuantities.Add(new SelectListItem { Text = quantity.ToString(), Value = quantity.ToString(), Selected = item.Quantity == quantity }); } var quantityUnit = await Db.QuantityUnits.GetQuantityUnitByIdAsync(product.QuantityUnitId ?? 0, _catalogSettings.ShowDefaultQuantityUnit); if (quantityUnit != null) { to.QuantityUnitName = quantityUnit.GetLocalized(x => x.Name); } if (product.IsRecurring) { to.RecurringInfo = T("ShoppingCart.RecurringPeriod", product.RecurringCycleLength, product.RecurringCyclePeriod.GetLocalizedEnum()); } if (product.CallForPrice) { to.UnitPrice = to.UnitPrice.WithPostFormat(T("Products.CallForPrice")); to.SubTotal = to.UnitPrice; } else if (item.BundleItem == null) { if (shoppingCartType == ShoppingCartType.ShoppingCart) { var subtotal = parameters?.CartSubtotal as ShoppingCartSubtotal; var lineItem = subtotal.LineItems.FirstOrDefault(x => x.Item.Item.Id == item.Id); var unitPrice = CurrencyService.ConvertFromPrimaryCurrency(lineItem.UnitPrice.FinalPrice.Amount, currency); to.UnitPrice = unitPrice.WithPostFormat(taxFormat); var itemSubtotal = CurrencyService.ConvertFromPrimaryCurrency(lineItem.Subtotal.FinalPrice.Amount, currency); to.SubTotal = itemSubtotal.WithPostFormat(taxFormat); if (lineItem.Subtotal.DiscountAmount > 0) { var itemDiscount = CurrencyService.ConvertFromPrimaryCurrency(lineItem.Subtotal.DiscountAmount.Amount, currency); to.Discount = itemDiscount.WithPostFormat(taxFormat); } to.BasePrice = _priceCalculationService.GetBasePriceInfo(product, unitPrice); } else { var calculationOptions = _priceCalculationService.CreateDefaultOptions(false, customer, null, batchContext); var calculationContext = await _priceCalculationService.CreateCalculationContextAsync(from, calculationOptions); var(unitPrice, itemSubtotal) = await _priceCalculationService.CalculateSubtotalAsync(calculationContext); to.UnitPrice = unitPrice.FinalPrice; to.SubTotal = itemSubtotal.FinalPrice; if (itemSubtotal.DiscountAmount > 0) { to.Discount = itemSubtotal.DiscountAmount; } } } if (item.BundleItem != null) { if (_shoppingCartSettings.ShowProductBundleImagesOnShoppingCart) { await from.MapAsync(to.Image, MediaSettings.CartThumbBundleItemPictureSize, to.ProductName); } } else { if (_shoppingCartSettings.ShowProductImagesOnShoppingCart) { await from.MapAsync(to.Image, MediaSettings.CartThumbPictureSize, to.ProductName); } } var itemWarnings = new List <string>(); var isValid = await ShoppingCartValidator.ValidateCartItemsAsync(new[] { from }, itemWarnings); if (!isValid) { to.Warnings.AddRange(itemWarnings); } var cart = await ShoppingCartService.GetCartItemsAsync(customer, shoppingCartType, _services.StoreContext.CurrentStore.Id); var attrWarnings = new List <string>(); isValid = await ShoppingCartValidator.ValidateProductAttributesAsync(item, cart, attrWarnings); if (!isValid) { to.Warnings.AddRange(attrWarnings); } }
/// <summary> /// Adds selected product attributes of a shopping cart item to be taken into account in the price calculation. /// For example required for price adjustments of attributes selected by the customer. /// Also adds selected attributes of bundle items if <see cref="Product.BundlePerItemPricing"/> is activated. /// </summary> /// <param name="context">The target product calculation context.</param> /// <param name="item">Shopping cart item.</param> public static void AddSelectedAttributes(this PriceCalculationContext context, OrganizedShoppingCartItem cartItem) { Guard.NotNull(context, nameof(context)); if (cartItem != null) { var item = cartItem.Item; context.AddSelectedAttributes(item); if (item.Product.ProductType == ProductType.BundledProduct && item.Product.BundlePerItemPricing) { cartItem.ChildItems.Each(x => context.AddSelectedAttributes(x.Item)); } } }