/// <summary> /// Gets the base price info for a product. /// </summary> /// <param name="priceCalculationService">Price calculation service.</param> /// <param name="product">The product to get the base price info for.</param> /// <param name="options">Price calculation options. The default options are used if <c>null</c>.</param> /// <returns>Base price info.</returns> public static async Task <string> GetBasePriceInfoAsync(this IPriceCalculationService priceCalculationService, Product product, PriceCalculationOptions options = null) { Guard.NotNull(priceCalculationService, nameof(priceCalculationService)); Guard.NotNull(product, nameof(product)); if (!product.BasePriceHasValue || product.BasePriceAmount == 0) { return(string.Empty); } options ??= priceCalculationService.CreateDefaultOptions(false); var context = new PriceCalculationContext(product, options); var price = await priceCalculationService.CalculatePriceAsync(context); return(priceCalculationService.GetBasePriceInfo(product, price.FinalPrice, options.TargetCurrency)); }
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); } }
public override async Task MapAsync(IEnumerable <OrganizedShoppingCartItem> from, MiniShoppingCartModel to, dynamic parameters = null) { Guard.NotNull(from, nameof(from)); Guard.NotNull(to, nameof(to)); var customer = _services.WorkContext.CurrentCustomer; to.ShowProductImages = _shoppingCartSettings.ShowProductImagesInMiniShoppingCart; to.ThumbSize = _mediaSettings.MiniCartThumbPictureSize; to.CurrentCustomerIsGuest = customer.IsGuest(); to.AnonymousCheckoutAllowed = _orderSettings.AnonymousCheckoutAllowed; to.DisplayMoveToWishlistButton = await _services.Permissions.AuthorizeAsync(Permissions.Cart.AccessWishlist); to.ShowBasePrice = _shoppingCartSettings.ShowBasePrice; to.TotalProducts = from.GetTotalQuantity(); if (!from.Any()) { return; } var taxFormat = _currencyService.GetTaxFormat(); var batchContext = _productService.CreateProductBatchContext(from.Select(x => x.Item.Product).ToArray(), null, customer, false); var subtotal = await _orderCalculationService.GetShoppingCartSubtotalAsync(from.ToList(), null, batchContext); var lineItems = subtotal.LineItems.ToDictionarySafe(x => x.Item.Item.Id); var currency = _services.WorkContext.WorkingCurrency; var subtotalWithoutDiscount = _currencyService.ConvertFromPrimaryCurrency(subtotal.SubtotalWithoutDiscount.Amount, currency); to.SubTotal = subtotalWithoutDiscount.WithPostFormat(taxFormat); // A customer should visit the shopping cart page before going to checkout if: //1. There is at least one checkout attribute that is reqired //2. Min order sub total is OK var checkoutAttributes = await _checkoutAttributeMaterializer.GetValidCheckoutAttributesAsync(from); to.DisplayCheckoutButton = !checkoutAttributes.Any(x => x.IsRequired); // Products sort descending (recently added products) foreach (var cartItem in from) { var item = cartItem.Item; var product = cartItem.Item.Product; var productSeName = await product.GetActiveSlugAsync(); var cartItemModel = new MiniShoppingCartModel.ShoppingCartItemModel { Id = item.Id, ProductId = product.Id, ProductName = product.GetLocalized(x => x.Name), ShortDesc = product.GetLocalized(x => x.ShortDescription), ProductSeName = productSeName, EnteredQuantity = item.Quantity, MaxOrderAmount = product.OrderMaximumQuantity, MinOrderAmount = product.OrderMinimumQuantity, QuantityStep = product.QuantityStep > 0 ? product.QuantityStep : 1, CreatedOnUtc = item.UpdatedOnUtc, ProductUrl = await _productUrlHelper.GetProductUrlAsync(productSeName, cartItem), QuantityUnitName = null, AttributeInfo = await _productAttributeFormatter.FormatAttributesAsync( item.AttributeSelection, product, null, ", ", includePrices : false, includeGiftCardAttributes : false, includeHyperlinks : false, batchContext : batchContext) }; if (cartItem.ChildItems != null && _shoppingCartSettings.ShowProductBundleImagesOnShoppingCart) { var bundleItems = cartItem.ChildItems.Where(x => x.Item.Id != item.Id && x.Item.BundleItem != null && !x.Item.BundleItem.HideThumbnail); foreach (var bundleItem in bundleItems) { var bundleItemModel = new MiniShoppingCartModel.ShoppingCartItemBundleItem { ProductName = bundleItem.Item.Product.GetLocalized(x => x.Name), ProductSeName = await bundleItem.Item.Product.GetActiveSlugAsync(), }; bundleItemModel.ProductUrl = await _productUrlHelper.GetProductUrlAsync( bundleItem.Item.ProductId, bundleItemModel.ProductSeName, bundleItem.Item.AttributeSelection); var file = await _db.ProductMediaFiles .AsNoTracking() .Include(x => x.MediaFile) .ApplyProductFilter(bundleItem.Item.ProductId) .FirstOrDefaultAsync(); if (file?.MediaFile != null) { var fileInfo = await _mediaService.GetFileByIdAsync(file.MediaFileId, MediaLoadFlags.AsNoTracking); bundleItemModel.ImageModel = new ImageModel { File = fileInfo, ThumbSize = MediaSettings.ThumbnailSizeXxs, Title = file.MediaFile.GetLocalized(x => x.Title)?.Value.NullEmpty() ?? T("Media.Manufacturer.ImageLinkTitleFormat", bundleItemModel.ProductName), Alt = file.MediaFile.GetLocalized(x => x.Alt)?.Value.NullEmpty() ?? T("Media.Manufacturer.ImageAlternateTextFormat", bundleItemModel.ProductName), NoFallback = _catalogSettings.HideProductDefaultPictures, }; } cartItemModel.BundleItems.Add(bundleItemModel); } } // Unit prices. if (product.CallForPrice) { cartItemModel.UnitPrice = T("Products.CallForPrice"); } else if (lineItems.TryGetValue(item.Id, out var lineItem)) { var unitPrice = _currencyService.ConvertFromPrimaryCurrency(lineItem.UnitPrice.FinalPrice.Amount, currency); cartItemModel.UnitPrice = unitPrice.WithPostFormat(taxFormat).ToString(true); if (unitPrice != 0 && to.ShowBasePrice) { cartItemModel.BasePriceInfo = _priceCalculationService.GetBasePriceInfo(item.Product, unitPrice, currency); } } // Image. if (_shoppingCartSettings.ShowProductImagesInMiniShoppingCart) { await cartItem.MapAsync(cartItemModel.Image, _mediaSettings.MiniCartThumbPictureSize, cartItemModel.ProductName); } to.Items.Add(cartItemModel); } }