示例#1
0
        protected void CalculateProductPrices(ProductVariant product, Currency currency, out decimal price, out decimal dicountedPrice)
        {
            decimal tax = 0, tax2 = 0;

            price          = _priceCalculationService.GetFinalPrice(product, DefaultCustomer, false, false);
            dicountedPrice = _priceCalculationService.GetFinalPrice(product, DefaultCustomer, true, false);

            price          = _taxService.GetProductPrice(product, price, DefaultCustomer, out tax);
            dicountedPrice = _taxService.GetProductPrice(product, dicountedPrice, DefaultCustomer, out tax2);

            //price = _currencyService.ConvertFromPrimaryStoreCurrency(price, currency);
            //dicountedPrice = _currencyService.ConvertFromPrimaryStoreCurrency(dicountedPrice, currency);
        }
示例#2
0
        /// <summary>
        /// Gets the base price info
        /// </summary>
        /// <param name="product">Product</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="priceFormatter">Price formatter</param>
        /// <param name="currencyService">Currency service</param>
        /// <param name="taxService">Tax service</param>
        /// <param name="priceCalculationService">Price calculation service</param>
        /// <param name="customer">Customer</param>
        /// <param name="currency">Target currency</param>
        /// <param name="priceAdjustment">Price adjustment</param>
        /// <returns>The base price info</returns>
        public static string GetBasePriceInfo(this Product product,
                                              ILocalizationService localizationService,
                                              IPriceFormatter priceFormatter,
                                              ICurrencyService currencyService,
                                              ITaxService taxService,
                                              IPriceCalculationService priceCalculationService,
                                              Customer customer,
                                              Currency currency,
                                              decimal priceAdjustment = decimal.Zero)
        {
            Guard.NotNull(product, nameof(product));
            Guard.NotNull(currencyService, nameof(currencyService));
            Guard.NotNull(taxService, nameof(taxService));
            Guard.NotNull(priceCalculationService, nameof(priceCalculationService));
            Guard.NotNull(customer, nameof(customer));
            Guard.NotNull(currency, nameof(currency));

            if (product.BasePriceHasValue && product.BasePriceAmount != decimal.Zero)
            {
                var currentPrice = priceCalculationService.GetFinalPrice(product, customer, true);
                var price        = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), customer, currency, out var taxrate);
                price = currencyService.ConvertFromPrimaryStoreCurrency(price, currency);

                return(product.GetBasePriceInfo(price, localizationService, priceFormatter, currency));
            }

            return(string.Empty);
        }
        private OrderItem PrepareDefaultOrderItemFromProduct(Order order, Product product)
        {
            var presetQty   = 1;
            var presetPrice =
                _priceCalculationService.GetFinalPrice(product, order.Customer, decimal.Zero, true, presetQty);

            var presetPriceInclTax =
                _taxService.GetProductPrice(product, presetPrice, true, order.Customer, out _);
            var presetPriceExclTax =
                _taxService.GetProductPrice(product, presetPrice, false, order.Customer, out _);

            var orderItem = new OrderItem
            {
                OrderItemGuid       = new Guid(),
                UnitPriceExclTax    = presetPriceExclTax,
                UnitPriceInclTax    = presetPriceInclTax,
                PriceInclTax        = presetPriceInclTax,
                PriceExclTax        = presetPriceExclTax,
                OriginalProductCost = _priceCalculationService.GetProductCost(product, null),
                Quantity            = presetQty,
                Product             = product,
                Order = order
            };

            return(orderItem);
        }
        /// <summary>
        /// Gets the base price info
        /// </summary>
        /// <param name="product">Product</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="priceFormatter">Price formatter</param>
        /// <param name="currencyService">Currency service</param>
        /// <param name="taxService">Tax service</param>
        /// <param name="priceCalculationService">Price calculation service</param>
        /// <param name="currency">Target currency</param>
        /// <param name="priceAdjustment">Price adjustment</param>
        /// <param name="languageInsensitive">Whether the result string should be language insensitive</param>
        /// <returns>The base price info</returns>
        public static string GetBasePriceInfo(this Product product,
                                              ILocalizationService localizationService,
                                              IPriceFormatter priceFormatter,
                                              ICurrencyService currencyService,
                                              ITaxService taxService,
                                              IPriceCalculationService priceCalculationService,
                                              Currency currency,
                                              decimal priceAdjustment  = decimal.Zero,
                                              bool languageInsensitive = false)
        {
            Guard.NotNull(product, nameof(product));
            Guard.NotNull(currencyService, nameof(currencyService));
            Guard.NotNull(taxService, nameof(taxService));
            Guard.NotNull(priceCalculationService, nameof(priceCalculationService));
            Guard.NotNull(currency, nameof(currency));

            if (product.BasePriceHasValue && product.BasePriceAmount != Decimal.Zero)
            {
                var workContext = EngineContext.Current.Resolve <IWorkContext>();

                var taxrate      = decimal.Zero;
                var currentPrice = priceCalculationService.GetFinalPrice(product, workContext.CurrentCustomer, true);
                var price        = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), out taxrate);

                price = currencyService.ConvertFromPrimaryStoreCurrency(price, currency);

                return(product.GetBasePriceInfo(price, localizationService, priceFormatter, currency, languageInsensitive));
            }

            return("");
        }
示例#5
0
        private async Task <(string Price, string PriceWithDiscount)> PreparePrice(Product product, GetSearchAutoComplete request)
        {
            string price, priceWithDiscount;

            decimal finalPriceWithoutDiscount =
                (await(_taxService.GetProductPrice(product,
                                                   (await _priceCalculationService.GetFinalPrice(product, request.Customer, request.Currency, includeDiscounts: false)).finalPrice))).productprice;

            var appliedPrice           = (await _priceCalculationService.GetFinalPrice(product, request.Customer, request.Currency, includeDiscounts: true));
            var finalPriceWithDiscount = (await _taxService.GetProductPrice(product, appliedPrice.finalPrice)).productprice;

            price             = _priceFormatter.FormatPrice(finalPriceWithoutDiscount);
            priceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount);

            return(price, priceWithDiscount);
        }
示例#6
0
        public ActionResult ProductTierPrices(int productId)
        {
            if (!_services.Permissions.Authorize(StandardPermissionProvider.DisplayPrices))
            {
                return(Content(""));
            }

            var product = _productService.GetProductById(productId);

            if (product == null)
            {
                throw new ArgumentException(T("Products.NotFound", productId));
            }


            if (!product.HasTierPrices)
            {
                // No tier prices
                return(Content(""));
            }

            var model = product.TierPrices
                        .OrderBy(x => x.Quantity)
                        .FilterByStore(_services.StoreContext.CurrentStore.Id)
                        .FilterForCustomer(_services.WorkContext.CurrentCustomer)
                        .ToList()
                        .RemoveDuplicatedQuantities()
                        .Select(tierPrice =>
            {
                var m = new ProductDetailsModel.TierPriceModel
                {
                    Quantity = tierPrice.Quantity,
                };
                decimal taxRate   = decimal.Zero;
                decimal priceBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, _services.WorkContext.CurrentCustomer, decimal.Zero, _catalogSettings.DisplayTierPricesWithDiscounts, tierPrice.Quantity), out taxRate);
                decimal price     = _currencyService.ConvertFromPrimaryStoreCurrency(priceBase, _services.WorkContext.WorkingCurrency);
                m.Price           = _priceFormatter.FormatPrice(price, true, false);
                return(m);
            })
                        .ToList();

            return(PartialView("Product.TierPrices", model));
        }
        /// <summary>
        /// Gets the base price
        /// </summary>
        /// <param name="product">Product</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="priceFormatter">Price formatter</param>
        /// <param name="currencyService">Currency service</param>
        /// <param name="taxService">Tax service</param>
        /// <param name="priceCalculationService">Price calculation service</param>
        /// <param name="currency">Target currency</param>
        /// <param name="priceAdjustment">Price adjustment</param>
        /// <param name="languageIndependent">Whether the result string should be language independent</param>
        /// <returns>The base price</returns>
        public static string GetBasePriceInfo(this Product product, ILocalizationService localizationService, IPriceFormatter priceFormatter,
                                              ICurrencyService currencyService, ITaxService taxService, IPriceCalculationService priceCalculationService,
                                              Currency currency, decimal priceAdjustment = decimal.Zero, bool languageIndependent = false)
        {
            if (product == null)
            {
                throw new ArgumentNullException("product");
            }

            if (localizationService == null && !languageIndependent)
            {
                throw new ArgumentNullException("localizationService");
            }

            if (product.BasePriceHasValue && product.BasePriceAmount != Decimal.Zero)
            {
                var workContext = EngineContext.Current.Resolve <IWorkContext>();

                var     taxrate      = decimal.Zero;
                var     currentPrice = priceCalculationService.GetFinalPrice(product, workContext.CurrentCustomer, true);
                decimal price        = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), out taxrate);

                price = currencyService.ConvertFromPrimaryStoreCurrency(price, currency);

                decimal basePriceValue = Convert.ToDecimal((price / product.BasePriceAmount) * product.BasePriceBaseAmount);

                string basePrice = priceFormatter.FormatPrice(basePriceValue, true, currency);
                string unit      = "{0} {1}".FormatWith(product.BasePriceBaseAmount, product.BasePriceMeasureUnit);

                if (languageIndependent)
                {
                    return("{0} / {1}".FormatWith(basePrice, unit));
                }

                return(localizationService.GetResource("Products.BasePriceInfo").FormatWith(basePrice, unit));
            }
            return("");
        }
        public void Can_get_final_product_price()
        {
            RunWithTestServiceProvider(() =>
            {
                var product = _productService.GetProductById(1);

                //customer
                var customer = new Customer();

                _priceCalcService.GetFinalPrice(product, customer, 0, false).Should().Be(12.34M);
                _priceCalcService.GetFinalPrice(product, customer, 0, false, 2).Should().Be(9M);
            });
        }
        public void Can_get_final_product_price()
        {
            var product = new Product
            {
                Id    = 1,
                Name  = "Product name 1",
                Price = 12.34M,
                CustomerEntersPrice = false,
                Published           = true,
            };

            //customer
            var customer = new Customer();

            _priceCalcService.GetFinalPrice(product, customer, 0, false, 1).ShouldEqual(12.34M);
            _priceCalcService.GetFinalPrice(product, customer, 0, false, 2).ShouldEqual(12.34M);
        }
示例#10
0
        private string WriteItem(XmlWriter writer, Store store, Product product, Currency currency)
        {
            var manu          = _manufacturerService.GetProductManufacturersByProductId(product.Id).FirstOrDefault();
            var mainImageUrl  = Helper.MainProductImageUrl(store, product);
            var googleProduct = GetByProductId(product.Id);
            var category      = ProductCategory(googleProduct);

            if (category.IsNullOrEmpty())
            {
                return(Helper.Resource("MissingDefaultCategory"));
            }

            var brand = (manu != null && manu.Manufacturer.Name.HasValue() ? manu.Manufacturer.Name : Settings.Brand);
            var mpn   = Helper.ManufacturerPartNumber(product);

            bool identifierExists = product.Gtin.HasValue() || brand.HasValue() || mpn.HasValue();

            writer.WriteElementString("g", "id", _googleNamespace, product.Id.ToString());

            writer.WriteStartElement("title");
            writer.WriteCData(product.Name.Truncate(70));
            writer.WriteEndElement();

            var description = Helper.BuildProductDescription(product, manu, d =>
            {
                if (product.FullDescription.IsNullOrEmpty() && product.ShortDescription.IsNullOrEmpty())
                {
                    var rnd = new Random();

                    switch (rnd.Next(1, 5))
                    {
                    case 1: return(d.Grow(Settings.AppendDescriptionText1, " "));

                    case 2: return(d.Grow(Settings.AppendDescriptionText2, " "));

                    case 3: return(d.Grow(Settings.AppendDescriptionText3, " "));

                    case 4: return(d.Grow(Settings.AppendDescriptionText4, " "));

                    case 5: return(d.Grow(Settings.AppendDescriptionText5, " "));
                    }
                }
                return(d);
            });

            writer.WriteStartElement("description");
            writer.WriteCData(description);
            writer.WriteEndElement();

            writer.WriteStartElement("g", "google_product_category", _googleNamespace);
            writer.WriteCData(category);
            writer.WriteFullEndElement();

            string productType = _categoryService.GetCategoryBreadCrumb(product);

            if (productType.HasValue())
            {
                writer.WriteStartElement("g", "product_type", _googleNamespace);
                writer.WriteCData(productType);
                writer.WriteFullEndElement();
            }

            writer.WriteElementString("link", Helper.ProductDetailUrl(store, product));
            writer.WriteElementString("g", "image_link", _googleNamespace, mainImageUrl);

            foreach (string additionalImageUrl in Helper.AdditionalProductImages(store, product, mainImageUrl))
            {
                writer.WriteElementString("g", "additional_image_link", _googleNamespace, additionalImageUrl);
            }

            writer.WriteElementString("g", "condition", _googleNamespace, Condition());
            writer.WriteElementString("g", "availability", _googleNamespace, Availability(product));

            decimal priceBase = _priceCalculationService.GetFinalPrice(product, null, _workContext.CurrentCustomer, decimal.Zero, true, 1);
            decimal price     = Helper.ConvertFromStoreCurrency(priceBase, currency);
            string  specialPriceDate;

            if (SpecialPrice(product, out specialPriceDate))
            {
                writer.WriteElementString("g", "sale_price", _googleNamespace, Helper.DecimalUsFormat(price) + " " + currency.CurrencyCode);
                writer.WriteElementString("g", "sale_price_effective_date", _googleNamespace, specialPriceDate);

                // get regular price
                decimal specialPrice = product.SpecialPrice.Value;
                product.SpecialPrice = null;
                priceBase            = _priceCalculationService.GetFinalPrice(product, null, _workContext.CurrentCustomer, decimal.Zero, true, 1);
                product.SpecialPrice = specialPrice;
                price = Helper.ConvertFromStoreCurrency(priceBase, currency);
            }

            writer.WriteElementString("g", "price", _googleNamespace, Helper.DecimalUsFormat(price) + " " + currency.CurrencyCode);

            writer.WriteCData("gtin", product.Gtin, "g", _googleNamespace);
            writer.WriteCData("brand", brand, "g", _googleNamespace);
            writer.WriteCData("mpn", mpn, "g", _googleNamespace);

            writer.WriteCData("gender", Gender(googleProduct), "g", _googleNamespace);
            writer.WriteCData("age_group", AgeGroup(googleProduct), "g", _googleNamespace);
            writer.WriteCData("color", Color(googleProduct), "g", _googleNamespace);
            writer.WriteCData("size", Size(googleProduct), "g", _googleNamespace);
            writer.WriteCData("material", Material(googleProduct), "g", _googleNamespace);
            writer.WriteCData("pattern", Pattern(googleProduct), "g", _googleNamespace);
            writer.WriteCData("item_group_id", ItemGroupId(googleProduct), "g", _googleNamespace);

            writer.WriteElementString("g", "online_only", _googleNamespace, Settings.OnlineOnly ? "y" : "n");
            writer.WriteElementString("g", "identifier_exists", _googleNamespace, identifierExists ? "TRUE" : "FALSE");

            if (Settings.ExpirationDays > 0)
            {
                writer.WriteElementString("g", "expiration_date", _googleNamespace, DateTime.UtcNow.AddDays(Settings.ExpirationDays).ToString("yyyy-MM-dd"));
            }

            if (Settings.ExportShipping)
            {
                string weightInfo, weight = Helper.DecimalUsFormat(product.Weight);
                string systemKey = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword;

                if (systemKey.IsCaseInsensitiveEqual("gram"))
                {
                    weightInfo = weight + " g";
                }
                else if (systemKey.IsCaseInsensitiveEqual("lb"))
                {
                    weightInfo = weight + " lb";
                }
                else if (systemKey.IsCaseInsensitiveEqual("ounce"))
                {
                    weightInfo = weight + " oz";
                }
                else
                {
                    weightInfo = weight + " kg";
                }

                writer.WriteElementString("g", "shipping_weight", _googleNamespace, weightInfo);
            }

            if (Settings.ExportBasePrice && product.BasePriceHasValue)
            {
                string measureUnit = BasePriceUnits(product.BasePriceMeasureUnit);

                if (BasePriceSupported(product.BasePriceBaseAmount ?? 0, measureUnit))
                {
                    string basePriceMeasure     = "{0} {1}".FormatWith(Helper.DecimalUsFormat(product.BasePriceAmount ?? decimal.Zero), measureUnit);
                    string basePriceBaseMeasure = "{0} {1}".FormatWith(product.BasePriceBaseAmount, measureUnit);

                    writer.WriteElementString("g", "unit_pricing_measure", _googleNamespace, basePriceMeasure);
                    writer.WriteElementString("g", "unit_pricing_base_measure", _googleNamespace, basePriceBaseMeasure);
                }
            }

            return(null);
        }
        private async Task PreparePriceModel(ProductOverviewModel model, Product product, Dictionary <string, string> res,
                                             bool forceRedirectionAfterAddingToCart, bool enableShoppingCart, bool displayPrices, bool enableWishlist,
                                             bool priceIncludesTax)
        {
            #region Prepare product price

            var priceModel = new ProductOverviewModel.ProductPriceModel {
                ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart
            };

            switch (product.ProductType)
            {
            case ProductType.GroupedProduct:
                {
                    #region Grouped product

                    var associatedProducts = await _productService.GetAssociatedProducts(product.Id, _storeContext.CurrentStore.Id);

                    //add to cart button (ignore "DisableBuyButton" property for grouped products)
                    priceModel.DisableBuyButton = !enableShoppingCart || !displayPrices;

                    //add to wishlist button (ignore "DisableWishlistButton" property for grouped products)
                    priceModel.DisableWishlistButton = !enableWishlist || !displayPrices;

                    //compare products
                    priceModel.DisableAddToCompareListButton = !_catalogSettings.CompareProductsEnabled;

                    //catalog price, not used in views, but it's for front developer
                    if (product.CatalogPrice > 0)
                    {
                        decimal catalogPrice = await _currencyService.ConvertFromPrimaryStoreCurrency(product.CatalogPrice, _workContext.WorkingCurrency);

                        priceModel.CatalogPrice = _priceFormatter.FormatPrice(catalogPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                    }

                    switch (associatedProducts.Count)
                    {
                    case 0:
                    {
                    }
                    break;

                    default:
                    {
                        //we have at least one associated product
                        //compare products
                        priceModel.DisableAddToCompareListButton = !_catalogSettings.CompareProductsEnabled;
                        if (displayPrices)
                        {
                            //find a minimum possible price
                            decimal?minPossiblePrice = null;
                            Product minPriceProduct  = null;
                            foreach (var associatedProduct in associatedProducts)
                            {
                                //calculate for the maximum quantity (in case if we have tier prices)
                                var tmpPrice = (await _priceCalculationService.GetFinalPrice(associatedProduct,
                                                                                             _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue)).finalPrice;
                                if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                {
                                    minPriceProduct  = associatedProduct;
                                    minPossiblePrice = tmpPrice;
                                }
                            }
                            if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                            {
                                if (minPriceProduct.CallForPrice)
                                {
                                    priceModel.OldPrice = null;
                                    priceModel.Price    = res["Products.CallForPrice"];
                                }
                                else if (minPossiblePrice.HasValue)
                                {
                                    //calculate prices
                                    decimal finalPriceBase = (await _taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, priceIncludesTax, _workContext.CurrentCustomer)).productprice;
                                    decimal finalPrice     = await _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _workContext.WorkingCurrency);

                                    priceModel.OldPrice   = null;
                                    priceModel.Price      = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax));
                                    priceModel.PriceValue = finalPrice;

                                    //PAngV baseprice (used in Germany)
                                    if (product.BasepriceEnabled)
                                    {
                                        priceModel.BasePricePAngV = await product.FormatBasePrice(finalPrice, _localizationService, _measureService, _currencyService, _workContext, _priceFormatter);
                                    }
                                }
                                else
                                {
                                    //Actually it's not possible (we presume that minimalPrice always has a value)
                                    //We never should get here
                                    Debug.WriteLine("Cannot calculate minPrice for product #{0}", product.Id);
                                }
                            }
                        }
                        else
                        {
                            //hide prices
                            priceModel.OldPrice = null;
                            priceModel.Price    = null;
                        }
                    }
                    break;
                    }

                    #endregion
                }
                break;

            case ProductType.SimpleProduct:
            case ProductType.Reservation:
            default:
            {
                #region Simple product

                //add to cart button
                priceModel.DisableBuyButton = product.DisableBuyButton || !enableShoppingCart || !displayPrices;

                //add to wishlist button
                priceModel.DisableWishlistButton = product.DisableWishlistButton || !enableWishlist || !displayPrices;
                //compare products
                priceModel.DisableAddToCompareListButton = !_catalogSettings.CompareProductsEnabled;

                //pre-order
                if (product.AvailableForPreOrder)
                {
                    priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                                      product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                    priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                }

                //catalog price, not used in views, but it's for front developer
                if (product.CatalogPrice > 0)
                {
                    decimal catalogPrice = await _currencyService.ConvertFromPrimaryStoreCurrency(product.CatalogPrice, _workContext.WorkingCurrency);

                    priceModel.CatalogPrice = _priceFormatter.FormatPrice(catalogPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                }

                //start price for product auction
                if (product.StartPrice > 0)
                {
                    decimal startPrice = await _currencyService.ConvertFromPrimaryStoreCurrency(product.StartPrice, _workContext.WorkingCurrency);

                    priceModel.StartPrice      = _priceFormatter.FormatPrice(startPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                    priceModel.StartPriceValue = startPrice;
                }

                //highest bid for product auction
                if (product.HighestBid > 0)
                {
                    decimal highestBid = await _currencyService.ConvertFromPrimaryStoreCurrency(product.HighestBid, _workContext.WorkingCurrency);

                    priceModel.HighestBid      = _priceFormatter.FormatPrice(highestBid, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                    priceModel.HighestBidValue = highestBid;
                }

                //prices
                if (displayPrices)
                {
                    if (!product.CustomerEntersPrice)
                    {
                        if (product.CallForPrice)
                        {
                            //call for price
                            priceModel.OldPrice = null;
                            priceModel.Price    = res["Products.CallForPrice"];
                        }
                        else
                        {
                            //prices

                            //calculate for the maximum quantity (in case if we have tier prices)
                            var infoprice = (await _priceCalculationService.GetFinalPrice(product,
                                                                                          _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue));

                            priceModel.AppliedDiscounts   = infoprice.appliedDiscounts;
                            priceModel.PreferredTierPrice = infoprice.preferredTierPrice;

                            decimal minPossiblePrice = infoprice.finalPrice;

                            decimal oldPriceBase   = (await _taxService.GetProductPrice(product, product.OldPrice, priceIncludesTax, _workContext.CurrentCustomer)).productprice;
                            decimal finalPriceBase = (await _taxService.GetProductPrice(product, minPossiblePrice, priceIncludesTax, _workContext.CurrentCustomer)).productprice;

                            decimal oldPrice = await _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency);

                            decimal finalPrice = await _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _workContext.WorkingCurrency);

                            //do we have tier prices configured?
                            var tierPrices = new List <TierPrice>();
                            if (product.TierPrices.Any())
                            {
                                tierPrices.AddRange(product.TierPrices.OrderBy(tp => tp.Quantity)
                                                    .FilterByStore(_storeContext.CurrentStore.Id)
                                                    .FilterForCustomer(_workContext.CurrentCustomer)
                                                    .FilterByDate()
                                                    .RemoveDuplicatedQuantities());
                            }
                            //When there is just one tier (with  qty 1),
                            //there are no actual savings in the list.
                            bool displayFromMessage = tierPrices.Any() && !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                            if (displayFromMessage)
                            {
                                priceModel.OldPrice   = null;
                                priceModel.Price      = String.Format(res["Products.PriceRangeFrom"], _priceFormatter.FormatPrice(finalPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax));
                                priceModel.PriceValue = finalPrice;
                            }
                            else
                            {
                                if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                {
                                    priceModel.OldPrice      = _priceFormatter.FormatPrice(oldPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                                    priceModel.OldPriceValue = oldPrice;
                                    priceModel.Price         = _priceFormatter.FormatPrice(finalPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                                    priceModel.PriceValue    = finalPrice;
                                }
                                else
                                {
                                    priceModel.OldPrice   = null;
                                    priceModel.Price      = _priceFormatter.FormatPrice(finalPrice, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, priceIncludesTax);
                                    priceModel.PriceValue = finalPrice;
                                }
                            }
                            if (product.ProductType == ProductType.Reservation)
                            {
                                //rental product
                                priceModel.OldPrice = _priceFormatter.FormatReservationProductPeriod(product, priceModel.OldPrice);
                                priceModel.Price    = _priceFormatter.FormatReservationProductPeriod(product, priceModel.Price);
                            }


                            //property for German market
                            //we display tax/shipping info only with "shipping enabled" for this product
                            //we also ensure this it's not free shipping
                            priceModel.DisplayTaxShippingInfo = _catalogSettings.DisplayTaxShippingInfoProductBoxes && product.IsShipEnabled && !product.IsFreeShipping;

                            //PAngV baseprice (used in Germany)
                            if (product.BasepriceEnabled)
                            {
                                priceModel.BasePricePAngV = await product.FormatBasePrice(finalPrice, _localizationService, _measureService, _currencyService, _workContext, _priceFormatter);
                            }
                        }
                    }
                }
                else
                {
                    //hide prices
                    priceModel.OldPrice = null;
                    priceModel.Price    = null;
                }

                #endregion
            }
            break;
            }

            model.ProductPrice = priceModel;

            #endregion
        }
示例#12
0
        private ProductVariantQuoteModel PrepareProductVariantQuoteModelForList(CustomerProductVariantQuote customerProductVariantQuote)
        {
            #region Product variant price
            var productVariant = _productService.GetProductVariantById(customerProductVariantQuote.ProductVariantId);
            if (productVariant == null || productVariant.Id == 0)
            {
                return(null);
            }
            string   productName = productVariant.FullProductName;
            Currency currency    = _currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId);
            if (productVariant != null && productVariant.CurrencyId.HasValue && (productVariant.CurrencyId.Value != _currencySettings.PrimaryStoreCurrencyId))
            {
                currency = _currencyService.GetCurrencyById(productVariant.CurrencyId.Value);
            }

            StatefulStorage.PerSession.Add <bool?>("SkipQuoteDiscountActivationCheck", () => (bool?)true);
            decimal taxRate      = decimal.Zero;
            var     customer     = _customerService.GetCustomerById(customerProductVariantQuote.CustomerId);
            decimal oldPriceBase = _taxService.GetProductPrice(productVariant, productVariant.OldPrice, out taxRate);
            decimal finalPriceWithoutDiscountBase = _taxService.GetProductPrice(productVariant, _priceCalculationService.GetFinalPrice(productVariant, customer, false, false), out taxRate);
            decimal finalPriceWithDiscountBase    = _taxService.GetProductPrice(productVariant, _priceCalculationService.GetFinalPrice(productVariant, customer, true, false), out taxRate);

            decimal oldPrice = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, currency);
            decimal finalPriceWithoutDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, currency);
            decimal finalPriceWithDiscount    = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, currency);

            string productVariantPriceOldPrice = String.Empty;
            if (finalPriceWithoutDiscountBase != oldPriceBase && oldPriceBase > decimal.Zero)
            {
                productVariantPriceOldPrice = _priceFormatter.FormatPrice(oldPrice, false, false);
            }
            string  productVariantPrice = _priceFormatter.FormatPrice(finalPriceWithoutDiscount, false, currency);
            string  productVariantPricePriceWithDiscount = "", productVariantPriceDiscountPrice = "", productVariantDiscountPercentage = "", productVariantPriceCurrency = "";
            decimal productVariantPricediscountValueBase = 0, productVariantPriceDiscountValue = 0, productVariantPriceValue = 0, productVariantPricePriceWithDiscountValue = 0;

            if (finalPriceWithoutDiscountBase != finalPriceWithDiscountBase)
            {
                IList <Discount> discounts = null;
                productVariantPricePriceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount, false, currency);
                productVariantPricediscountValueBase = _priceCalculationService.GetDiscountAmount(productVariant, customer, 0, out discounts, false);
                productVariantPriceDiscountValue     = _currencyService.ConvertFromPrimaryStoreCurrency(productVariantPricediscountValueBase, _workContext.WorkingCurrency);
                productVariantPriceDiscountPrice     = _priceFormatter.FormatPrice(productVariantPricediscountValueBase, true, false);

                if (_workContext.WorkingLanguage.DisplayOrder == 2)
                {
                    productVariantDiscountPercentage = String.Format("({0}%)", ((int)discounts.First().DiscountPercentage).ToString());
                }
                else
                {
                    productVariantDiscountPercentage = String.Format("(%{0})", ((int)discounts.First().DiscountPercentage).ToString());
                }
            }
            productVariantPriceValue = finalPriceWithoutDiscount;
            productVariantPricePriceWithDiscountValue = finalPriceWithDiscount;
            productVariantPriceCurrency = CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol;
            //////

            StatefulStorage.PerSession.Remove <bool?>("SkipQuoteDiscountActivationCheck");

            var pvpModel = new ProductVariantQuoteModel.ProductVariantPriceModel()
            {
                Price                  = productVariantPrice,
                PriceWithDiscount      = productVariantPricePriceWithDiscount,
                DiscountValue          = productVariantPriceDiscountValue,
                DiscountPrice          = productVariantPriceDiscountPrice,
                DiscountPercentage     = productVariantDiscountPercentage,
                PriceValue             = productVariantPriceValue,
                PriceWithDiscountValue = productVariantPricePriceWithDiscountValue,
                Currency               = productVariantPriceCurrency,
                OldPrice               = productVariantPriceOldPrice,
            };


            #endregion

            string name  = customerProductVariantQuote.Name;
            string phoneNumber = customerProductVariantQuote.PhoneNumber;
            try
            {
                Customer cust = _customerService.GetCustomerById(customerProductVariantQuote.CustomerId);
                if (cust != null)
                {
                    if (!cust.IsGuest())
                    {
                        name = cust.GetFullName();
                        if (cust.Addresses.Count() > 0)
                        {
                            phoneNumber = cust.Addresses.FirstOrDefault().PhoneNumber;
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
            return(new ProductVariantQuoteModel()
            {
                Id = customerProductVariantQuote.Id,
                ProductVariantId = customerProductVariantQuote.ProductVariantId,
                Email = customerProductVariantQuote.Email,
                PhoneNumber = phoneNumber,
                Enquiry = customerProductVariantQuote.Enquiry,
                Name = name,
                ManufacturerName = _productService.GetProductById(customerProductVariantQuote.ProductVariant.ProductId).GetDefaultManufacturer().Name,
                ProductName = productName,
                Sku = productVariant.Sku,
                ProductVariantPrice = pvpModel,
                Description = customerProductVariantQuote.Description,
                RequestDate = _dateTimeHelper.ConvertToUserTime(customerProductVariantQuote.RequestDate, DateTimeKind.Utc),
                PriceWithDiscount = customerProductVariantQuote.PriceWithDiscount,
                PriceWithoutDiscount = customerProductVariantQuote.PriceWithoutDiscount,
                DiscountPercentage = customerProductVariantQuote.DiscountPercentage,
                ActivateDate = customerProductVariantQuote.ActivateDate,
            });
        }
        public void Can_get_final_product_price()
        {
            var product = new Product
            {
                Id    = "1",
                Name  = "product name 01",
                Price = 49.99M,
                CustomerEntersPrice = false,
                Published           = true
            };

            var customer = new Customer();

            Assert.AreEqual(49.99M, _priceCalcService.GetFinalPrice(product, customer, 0, false, 1));
            //returned price FOR ONE UNIT should be the same, even if quantity is different than 1
            Assert.AreEqual(49.99M, _priceCalcService.GetFinalPrice(product, customer, 0, false, 10));
        }
示例#14
0
        public static IEnumerable <ProductOverviewModel> PrepareProductOverviewModels(this Controller controller,
                                                                                      IWorkContext workContext,
                                                                                      IStoreContext storeContext,
                                                                                      ICategoryService categoryService,
                                                                                      IProductService productService,
                                                                                      ISpecificationAttributeService specificationAttributeService,
                                                                                      IPriceCalculationService priceCalculationService,
                                                                                      IPriceFormatter priceFormatter,
                                                                                      IPermissionService permissionService,
                                                                                      ILocalizationService localizationService,
                                                                                      ITaxService taxService,
                                                                                      ICurrencyService currencyService,
                                                                                      IPictureService pictureService,
                                                                                      IWebHelper webHelper,
                                                                                      ICacheManager cacheManager,
                                                                                      CatalogSettings catalogSettings,
                                                                                      MediaSettings mediaSettings,
                                                                                      IEnumerable <Product> products,
                                                                                      bool preparePriceModel                 = true, bool preparePictureModel = true,
                                                                                      int?productThumbPictureSize            = null, bool prepareSpecificationAttributes = false,
                                                                                      bool forceRedirectionAfterAddingToCart = false)
        {
            if (products == null)
            {
                throw new ArgumentNullException("products");
            }

            var models = new List <ProductOverviewModel>();

            foreach (var product in products)
            {
                var model = new ProductOverviewModel
                {
                    Id               = product.Id,
                    Name             = product.GetLocalized(x => x.Name),
                    ShortDescription = product.GetLocalized(x => x.ShortDescription),
                    FullDescription  = product.GetLocalized(x => x.FullDescription),
                    SeName           = product.GetSeName(),
                    ProductType      = product.ProductType,
                    MarkAsNew        = product.MarkAsNew &&
                                       (!product.MarkAsNewStartDateTimeUtc.HasValue || product.MarkAsNewStartDateTimeUtc.Value < DateTime.UtcNow) &&
                                       (!product.MarkAsNewEndDateTimeUtc.HasValue || product.MarkAsNewEndDateTimeUtc.Value > DateTime.UtcNow)
                };
                //price
                if (preparePriceModel)
                {
                    #region Prepare product price

                    var priceModel = new ProductOverviewModel.ProductPriceModel
                    {
                        ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart
                    };

                    switch (product.ProductType)
                    {
                    case ProductType.GroupedProduct:
                    {
                        #region Grouped product

                        var associatedProducts = productService.GetAssociatedProducts(product.Id, storeContext.CurrentStore.Id);

                        //add to cart button (ignore "DisableBuyButton" property for grouped products)
                        priceModel.DisableBuyButton = !permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                                      !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //add to wishlist button (ignore "DisableWishlistButton" property for grouped products)
                        priceModel.DisableWishlistButton = !permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                                           !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //compare products
                        priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                        switch (associatedProducts.Count)
                        {
                        case 0:
                        {
                            //no associated products
                        }
                        break;

                        default:
                        {
                            //we have at least one associated product
                            //compare products
                            priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                            //priceModel.AvailableForPreOrder = false;

                            if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                            {
                                //find a minimum possible price
                                decimal?minPossiblePrice = null;
                                Product minPriceProduct  = null;
                                foreach (var associatedProduct in associatedProducts)
                                {
                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    var tmpPrice = priceCalculationService.GetFinalPrice(associatedProduct,
                                                                                         workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                                    if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                    {
                                        minPriceProduct  = associatedProduct;
                                        minPossiblePrice = tmpPrice;
                                    }
                                }
                                if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                                {
                                    if (minPriceProduct.CallForPrice)
                                    {
                                        priceModel.OldPrice = null;
                                        priceModel.Price    = localizationService.GetResource("Products.CallForPrice");
                                    }
                                    else if (minPossiblePrice.HasValue)
                                    {
                                        //calculate prices
                                        decimal taxRate;
                                        decimal finalPriceBase = taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                                        decimal finalPrice     = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                        priceModel.OldPrice   = null;
                                        priceModel.Price      = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));
                                        priceModel.PriceValue = finalPrice;
                                    }
                                    else
                                    {
                                        //Actually it's not possible (we presume that minimalPrice always has a value)
                                        //We never should get here
                                        Debug.WriteLine("Cannot calculate minPrice for product #{0}", product.Id);
                                    }
                                }
                            }
                            else
                            {
                                //hide prices
                                priceModel.OldPrice = null;
                                priceModel.Price    = null;
                            }
                        }
                        break;
                        }

                        #endregion
                    }
                    break;

                    case ProductType.SimpleProduct:
                    default:
                    {
                        #region Simple product

                        //add to cart button
                        priceModel.DisableBuyButton = product.DisableBuyButton ||
                                                      !permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                                      !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //add to wishlist button
                        priceModel.DisableWishlistButton = product.DisableWishlistButton ||
                                                           !permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                                           !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);
                        //compare products
                        priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;

                        //rental
                        priceModel.IsRental = product.IsRental;

                        //pre-order
                        if (product.AvailableForPreOrder)
                        {
                            priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                                              product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                            priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                        }

                        //prices
                        if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            if (!product.CustomerEntersPrice)
                            {
                                if (product.CallForPrice)
                                {
                                    //call for price
                                    priceModel.OldPrice = null;
                                    priceModel.Price    = localizationService.GetResource("Products.CallForPrice");
                                }
                                else
                                {
                                    //prices

                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    decimal minPossiblePrice = priceCalculationService.GetFinalPrice(product,
                                                                                                     workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);

                                    decimal taxRate;
                                    decimal oldPriceBase   = taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                                    decimal finalPriceBase = taxService.GetProductPrice(product, minPossiblePrice, out taxRate);

                                    decimal oldPrice   = currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, workContext.WorkingCurrency);
                                    decimal finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                    //do we have tier prices configured?
                                    var tierPrices = new List <TierPrice>();
                                    if (product.HasTierPrices)
                                    {
                                        tierPrices.AddRange(product.TierPrices
                                                            .OrderBy(tp => tp.Quantity)
                                                            .ToList()
                                                            .FilterByStore(storeContext.CurrentStore.Id)
                                                            .FilterForCustomer(workContext.CurrentCustomer)
                                                            .RemoveDuplicatedQuantities());
                                    }
                                    //When there is just one tier (with  qty 1),
                                    //there are no actual savings in the list.
                                    bool displayFromMessage = tierPrices.Count > 0 &&
                                                              !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                                    if (displayFromMessage)
                                    {
                                        priceModel.OldPrice   = null;
                                        priceModel.Price      = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));
                                        priceModel.PriceValue = finalPrice;
                                    }
                                    else
                                    {
                                        if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                        {
                                            priceModel.OldPrice   = priceFormatter.FormatPrice(oldPrice);
                                            priceModel.Price      = priceFormatter.FormatPrice(finalPrice);
                                            priceModel.PriceValue = finalPrice;
                                        }
                                        else
                                        {
                                            priceModel.OldPrice   = null;
                                            priceModel.Price      = priceFormatter.FormatPrice(finalPrice);
                                            priceModel.PriceValue = finalPrice;
                                        }
                                    }
                                    if (product.IsRental)
                                    {
                                        //rental product
                                        priceModel.OldPrice = priceFormatter.FormatRentalProductPeriod(product, priceModel.OldPrice);
                                        priceModel.Price    = priceFormatter.FormatRentalProductPeriod(product, priceModel.Price);
                                    }


                                    //property for German market
                                    //we display tax/shipping info only with "shipping enabled" for this product
                                    //we also ensure this it's not free shipping
                                    priceModel.DisplayTaxShippingInfo = catalogSettings.DisplayTaxShippingInfoProductBoxes &&
                                                                        product.IsShipEnabled &&
                                                                        !product.IsFreeShipping;
                                }
                            }
                        }
                        else
                        {
                            //hide prices
                            priceModel.OldPrice = null;
                            priceModel.Price    = null;
                        }

                        #endregion
                    }
                    break;
                    }

                    model.ProductPrice = priceModel;

                    #endregion
                }

                //picture
                if (preparePictureModel)
                {
                    #region Prepare product picture

                    //If a size has been set in the view, we use it in priority
                    int pictureSize = productThumbPictureSize.HasValue ? productThumbPictureSize.Value : mediaSettings.ProductThumbPictureSize;
                    //prepare picture model
                    var defaultProductPictureCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DEFAULTPICTURE_MODEL_KEY, product.Id, pictureSize, true, workContext.WorkingLanguage.Id, webHelper.IsCurrentConnectionSecured(), storeContext.CurrentStore.Id);
                    model.DefaultPictureModel = cacheManager.Get(defaultProductPictureCacheKey, () =>
                    {
                        var picture      = pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
                        var pictureModel = new PictureModel
                        {
                            ImageUrl         = pictureService.GetPictureUrl(picture, pictureSize),
                            FullSizeImageUrl = pictureService.GetPictureUrl(picture)
                        };
                        //"title" attribute
                        pictureModel.Title = (picture != null && !string.IsNullOrEmpty(picture.TitleAttribute)) ?
                                             picture.TitleAttribute :
                                             string.Format(localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name);
                        //"alt" attribute
                        pictureModel.AlternateText = (picture != null && !string.IsNullOrEmpty(picture.AltAttribute)) ?
                                                     picture.AltAttribute :
                                                     string.Format(localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name);

                        return(pictureModel);
                    });

                    #endregion
                }

                //specs
                if (prepareSpecificationAttributes)
                {
                    model.SpecificationAttributeModels = PrepareProductSpecificationModel(controller, workContext,
                                                                                          specificationAttributeService, cacheManager, product);
                }

                //reviews
                model.ReviewOverviewModel = controller.PrepareProductReviewOverviewModel(storeContext, catalogSettings, cacheManager, product);

                models.Add(model);
            }
            return(models);
        }
        /// <summary>
        /// Generate a feed
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="store">Store</param>
        /// <returns>Generated feed</returns>
        public void GenerateFeed(Stream stream, Store store)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (store == null)
            {
                throw new ArgumentNullException("store");
            }

            const string zboziBaseNamespace = "http://www.zbozi.cz/ns/offer/1.0";

            var settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8
            };

            //language
            var languageId = 0;
            var languages  = _languageService.GetAllLanguages(storeId: store.Id);

            //if we have only one language, let's use it
            if (languages.Count == 1)
            {
                //let's use the first one
                var language = languages.FirstOrDefault();
                languageId = language != null ? language.Id : 0;
            }
            //otherwise, use the current one
            if (languageId == 0)
            {
                languageId = _workContext.WorkingLanguage.Id;
            }

            //we load all google products here using one SQL request (performance optimization)
            var allzboziProducts = _zboziService.GetAll();

            var shippingMethodList = _shippingService.GetAllShippingMethods(27);


            using (var writer = XmlWriter.Create(stream, settings))
            {
                //Generate feed according to the following specs: https://napoveda.seznam.cz/cz/zbozi/specifikace-xml-pro-obchody/specifikace-xml-feedu/
                writer.WriteStartDocument();
                writer.WriteStartElement("SHOP", zboziBaseNamespace);
                //writer.WriteAttributeString("xmlns", zboziBaseNamespace);
                //writer.WriteAttributeString("xmlns", "", null, zboziBaseNamespace);

                var products1 = _productService.SearchProducts(storeId: store.Id, visibleIndividuallyOnly: true);
                foreach (var product1 in products1)
                {
                    var productsToProcess = new List <Product>();
                    switch (product1.ProductType)
                    {
                    case ProductType.SimpleProduct:
                    {
                        //simple product doesn't have child products
                        productsToProcess.Add(product1);
                    }
                    break;

                    case ProductType.GroupedProduct:
                    {
                        //grouped products could have several child products
                        var associatedProducts = _productService.GetAssociatedProducts(product1.Id, store.Id);
                        productsToProcess.AddRange(associatedProducts);
                    }
                    break;

                    default:
                        continue;
                    }
                    foreach (var product in productsToProcess)
                    {
                        writer.WriteStartElement("SHOPITEM");

                        #region Basic Product Information

                        //id [id]- An identifier of the item
                        writer.WriteElementString("ITEM_ID", product.Id.ToString());

                        //title [title] - Title of the item
                        writer.WriteStartElement("PRODUCT");
                        var title = product.GetLocalized(x => x.Name, languageId);
                        //title should be not longer than 70 characters
                        if (title.Length > 70)
                        {
                            title = title.Substring(0, 70);
                        }
                        writer.WriteCData(title);
                        writer.WriteEndElement();                         // title

                        //description [description] - Description of the item
                        writer.WriteStartElement("DESCRIPTION");
                        string description = product.GetLocalized(x => x.FullDescription, languageId);
                        if (String.IsNullOrEmpty(description))
                        {
                            description = product.GetLocalized(x => x.ShortDescription, languageId);
                        }
                        if (String.IsNullOrEmpty(description))
                        {
                            description = product.GetLocalized(x => x.Name, languageId);                             //description is required
                        }
                        //resolving character encoding issues in your data feed
                        description = StripInvalidChars(description, true);
                        writer.WriteCData(description);
                        writer.WriteEndElement();                         // description



                        //google product category [google_product_category] - Google's category of the item
                        //the category of the product according to Google’s product taxonomy. http://www.google.com/support/merchants/bin/answer.py?answer=160081
                        string googleProductCategory = "";
                        //var googleProduct = _googleService.GetByProductId(product.Id);
                        var zboziProduct = allzboziProducts.FirstOrDefault(x => x.ProductId == product.Id);
                        if (zboziProduct != null)
                        {
                            googleProductCategory = zboziProduct.Taxonomy;
                        }
                        if (String.IsNullOrEmpty(googleProductCategory))
                        {
                            googleProductCategory = _zboziShoppingSettings.DefaultGoogleCategory;
                        }
                        if (String.IsNullOrEmpty(googleProductCategory))
                        {
                            throw new NopException("Není nastavena základní kategorie");
                        }
                        writer.WriteStartElement("CATEGORYTEXT");
                        writer.WriteCData(googleProductCategory);
                        writer.WriteFullEndElement();                         // g:google_product_category

                        string zboziCPC = "";
                        if (zboziProduct != null)
                        {
                            zboziCPC = zboziProduct.MAX_CPC;
                        }

                        if (!string.IsNullOrEmpty(zboziCPC))
                        {
                            decimal result = 0;
                            if (decimal.TryParse(zboziCPC, out result))
                            {
                                writer.WriteElementString("MAX_CPC", zboziCPC);
                            }
                            else
                            {
                                throw new Exception("Parametr MAX_CPC musí obsahovat číselnou hodnotu. ");
                            }
                        }

                        string zboziCPC_serach = "";
                        if (zboziProduct != null)
                        {
                            zboziCPC_serach = zboziProduct.MAX_CPC_SEARCH;
                        }

                        if (!string.IsNullOrEmpty(zboziCPC_serach))
                        {
                            decimal result = 0;
                            if (decimal.TryParse(zboziCPC_serach, out result))
                            {
                                writer.WriteElementString("MAX_CPC_SEARCH", zboziCPC_serach);
                            }
                            else
                            {
                                throw new Exception("Parametr MAX_CPC_SEARCH musí obsahovat číselnou hodnotu. ");
                            }
                        }



                        string EXTRA_MESSAGE = "";
                        if (zboziProduct != null)
                        {
                            EXTRA_MESSAGE = zboziProduct.EXTRA_MESSAGE;
                        }

                        if (!string.IsNullOrEmpty(EXTRA_MESSAGE))
                        {
                            writer.WriteElementString("EXTRA_MESSAGE", EXTRA_MESSAGE);
                        }



                        string productName = "";
                        if (zboziProduct != null)
                        {
                            productName = zboziProduct.ProductName;
                        }

                        if (!string.IsNullOrEmpty(productName))
                        {
                            writer.WriteStartElement("PRODUCTNAME");
                            writer.WriteCData(productName);
                            writer.WriteFullEndElement();                             //
                        }
                        else
                        {
                            writer.WriteStartElement("PRODUCTNAME");
                            writer.WriteCData(title);
                            writer.WriteFullEndElement();                             //
                        }



                        // params
                        var parameters = "";
                        if (zboziProduct != null)
                        {
                            parameters = zboziProduct.Params;
                        }

                        if (string.IsNullOrEmpty(parameters) && product.ProductSpecificationAttributes.Count() > 0)
                        {
                            // progenerujeme vsechny parametry
                            foreach (var productSpecificAtribut in product.ProductSpecificationAttributes)
                            {
                                var option = productSpecificAtribut.SpecificationAttributeOption;
                                var name   = option.SpecificationAttribute.Name;
                                var value  = option.Name;

                                writer.WriteStartElement("PARAM");

                                writer.WriteStartElement("PARAM_NAME");
                                writer.WriteString(name);
                                writer.WriteEndElement();

                                writer.WriteStartElement("VAL");
                                writer.WriteString(value);
                                writer.WriteEndElement();

                                writer.WriteFullEndElement();                                 // g:


                                //var values = mapping.ProductAttributeValues.Where(e=>e.)
                            }
                        }
                        else
                        {
                            // prepiseme hodnotu
                        }


                        ////product type [product_type] - Your category of the item
                        //var defaultProductCategory = _categoryService
                        //    .GetProductCategoriesByProductId(product.Id, store.Id)
                        //    .FirstOrDefault();
                        //if (defaultProductCategory != null)
                        //{
                        //    //TODO localize categories
                        //    var category = defaultProductCategory.Category
                        //        .GetFormattedBreadCrumb(_categoryService, separator: ">", languageId: languageId);
                        //    if (!String.IsNullOrEmpty((category)))
                        //    {
                        //        writer.WriteStartElement("g", "product_type", googleBaseNamespace);
                        //        writer.WriteCData(category);
                        //        writer.WriteFullEndElement(); // g:product_type
                        //    }
                        //}

                        //link [link] - URL directly linking to your item's page on your website
                        var productUrl = string.Format("{0}{1}", store.Url, product.GetSeName(languageId));
                        writer.WriteElementString("URL", productUrl);

                        //image link [image_link] - URL of an image of the item
                        //additional images [additional_image_link]
                        //up to 10 pictures
                        const int maximumPictures = 10;
                        var       pictures        = _pictureService.GetPicturesByProductId(product.Id, maximumPictures);
                        for (int i = 0; i < pictures.Count; i++)
                        {
                            var picture  = pictures[i];
                            var imageUrl = _pictureService.GetPictureUrl(picture,
                                                                         _zboziShoppingSettings.ProductPictureSize,
                                                                         storeLocation: store.Url);

                            if (i == 0)
                            {
                                //default image
                                writer.WriteElementString("IMGURL", imageUrl);
                            }
                            //else
                            //{
                            //	//additional image
                            //	writer.WriteElementString("IMGURL_ALTERNATIVE", imageUrl);
                            //}
                        }
                        if (!pictures.Any())
                        {
                            //no picture? submit a default one
                            var imageUrl = _pictureService.GetDefaultPictureUrl(_zboziShoppingSettings.ProductPictureSize, storeLocation: store.Url);
                            writer.WriteElementString("IMGURL", imageUrl);
                        }


                        #endregion

                        #region Availability & Price


                        //price [price] - Price of the item
                        var     currency = GetUsedCurrency();
                        decimal finalPriceBase;
                        if (_zboziShoppingSettings.PricesConsiderPromotions)
                        {
                            var minPossiblePrice = _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer);

                            if (product.HasTierPrices)
                            {
                                //calculate price for the maximum quantity if we have tier prices, and choose minimal
                                minPossiblePrice = Math.Min(minPossiblePrice,
                                                            _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, quantity: int.MaxValue));
                            }

                            decimal taxRate;
                            finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out taxRate);
                        }
                        else
                        {
                            finalPriceBase = product.Price;
                        }
                        decimal price = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, currency);
                        //round price now so it matches the product details page
                        price = RoundingHelper.RoundPrice(price);

                        //writer.WriteElementString("g", "price", googleBaseNamespace,
                        //                          price.ToString(new CultureInfo("en-US", false).NumberFormat) + " " +
                        //                          currency.CurrencyCode);


                        if (price == 0)
                        {
                            writer.WriteElementString("PRICE_VAT", "0");
                        }
                        else
                        {
                            writer.WriteElementString("PRICE_VAT", price.ToString("#,##"));
                        }

                        #endregion

                        #region Unique Product Identifiers

                        /* Unique product identifiers such as UPC, EAN, JAN or ISBN allow us to show your listing on the appropriate product page. If you don't provide the required unique product identifiers, your store may not appear on product pages, and all your items may be removed from Product Search.
                         * We require unique product identifiers for all products - except for custom made goods. For apparel, you must submit the 'brand' attribute. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute. In all cases, we recommend you submit all three attributes.
                         * You need to submit at least two attributes of 'brand', 'gtin' and 'mpn', but we recommend that you submit all three if available. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute, but we recommend that you include 'brand' and 'mpn' if available.
                         */

                        //GTIN [gtin] - GTIN
                        var gtin = product.Gtin;
                        if (!String.IsNullOrEmpty(gtin))
                        {
                            writer.WriteStartElement("EAN");
                            writer.WriteCData(gtin);
                            writer.WriteFullEndElement();                             // g:gtin
                        }

                        //brand [brand] - Brand of the item
                        var defaultManufacturer =
                            _manufacturerService.GetProductManufacturersByProductId((product.Id)).FirstOrDefault();
                        if (defaultManufacturer != null)
                        {
                            writer.WriteStartElement("MANUFACTURER");
                            writer.WriteCData(defaultManufacturer.Manufacturer.Name);
                            writer.WriteFullEndElement();                             // g:brand
                        }


                        //mpn [mpn] - Manufacturer Part Number (MPN) of the item
                        var mpn = product.ManufacturerPartNumber;
                        if (!String.IsNullOrEmpty(mpn))
                        {
                            writer.WriteStartElement("PRODUCTNO");
                            writer.WriteCData(mpn);
                            writer.WriteFullEndElement();                             // g:mpn
                        }

                        //identifier exists [identifier_exists] - Submit custom goods
                        //if (googleProduct != null && googleProduct.CustomGoods)
                        //{
                        //    writer.WriteElementString("g", "identifier_exists", googleBaseNamespace, "FALSE");
                        //}

                        #endregion

                        #region Apparel Products



                        #endregion

                        #region Tax & Shipping


                        string deliveryDate = "0";

                        if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                            product.BackorderMode == BackorderMode.NoBackorders &&
                            product.GetTotalStockQuantity() <= 0)
                        {
                            // neni skladem a ma dobu pro doruceni
                            if (product.DeliveryDateId > 0)
                            {
                                var deliveryDateRecord = _dateRangeService.GetDeliveryDateById(product.DeliveryDateId);
                                deliveryDate = deliveryDateRecord.Name;
                            }
                            else
                            {
                                deliveryDate = _zboziShoppingSettings.DefaultDeliveryDate;
                            }
                        }

                        writer.WriteStartElement("DELIVERY_DATE");
                        writer.WriteString(deliveryDate);
                        writer.WriteFullEndElement();                         //



                        #endregion

                        writer.WriteEndElement();                         // item
                    }
                }


                writer.WriteEndElement();                 // shop
                writer.WriteEndDocument();
            }
        }
示例#16
0
        /// <summary>
        /// Gets the base price
        /// </summary>
        /// <param name="product">Product</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="priceFormatter">Price formatter</param>
        /// <param name="priceAdjustment">Price adjustment</param>
        /// <param name="languageIndependent">Whether the result string should be language independent</param>
        /// <returns>The base price</returns>
        public static string GetBasePriceInfo(this Product product, ILocalizationService localizationService, IPriceFormatter priceFormatter,
            ICurrencyService currencyService, ITaxService taxService, IPriceCalculationService priceCalculationService,
            Currency currency, decimal priceAdjustment = decimal.Zero, bool languageIndependent = false)
        {
            if (product == null)
                throw new ArgumentNullException("product");

            if (localizationService == null && !languageIndependent)
                throw new ArgumentNullException("localizationService");

            if (product.BasePriceHasValue && product.BasePriceAmount != Decimal.Zero)
            {
                var workContext = EngineContext.Current.Resolve<IWorkContext>();

                var taxrate = decimal.Zero;
                var currentPrice = priceCalculationService.GetFinalPrice(product, workContext.CurrentCustomer, true);
                decimal price = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), out taxrate);

                price = currencyService.ConvertFromPrimaryStoreCurrency(price, currency);

                decimal basePriceValue = Convert.ToDecimal((price / product.BasePriceAmount) * product.BasePriceBaseAmount);

                string basePrice = priceFormatter.FormatPrice(basePriceValue, true, currency);
                string unit = "{0} {1}".FormatWith(product.BasePriceBaseAmount, product.BasePriceMeasureUnit);

                if (languageIndependent)
                {
                    return "{0} / {1}".FormatWith(basePrice, unit);
                }

                return localizationService.GetResource("Products.BasePriceInfo").FormatWith(basePrice, unit);
            }
            return "";
        }
        public static string PreparePrice(this Product product, IWorkContext workContext, IStoreContext storeContext, IProductService productService, IPriceCalculationService priceCalculationService, IPriceFormatter priceFormatter, IPermissionService permissionService, ILocalizationService localizationService, ITaxService taxService, ICurrencyService currencyService)
        {
            decimal taxRate = new decimal();
            //decimal taxRate = new decimal();
            string str;
            bool   flag;

            if (product == null)
            {
                throw new ArgumentNullException("product");
            }
            string      price       = "0";
            ProductType productType = product.ProductType;

            if (productType != ProductType.SimpleProduct)
            {
                if (productType != ProductType.GroupedProduct)
                {
                    // goto Label2;
                }
                IList <Product> associatedProducts = productService.GetAssociatedProducts(product.Id, storeContext.CurrentStore.Id, 0, false);
                if (associatedProducts.Count == 0)
                {
                    price = "0";
                }
                else if (!permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                {
                    price = "0";
                }
                else
                {
                    decimal?minPossiblePrice = null;
                    Product minPriceProduct  = null;
                    foreach (Product associatedProduct in associatedProducts)
                    {
                        decimal tmpPrice = priceCalculationService.GetFinalPrice(associatedProduct, workContext.CurrentCustomer, decimal.Zero, true, 2147483647);
                        if ((!minPossiblePrice.HasValue ? true : tmpPrice < minPossiblePrice.Value))
                        {
                            minPriceProduct  = associatedProduct;
                            minPossiblePrice = new decimal?(tmpPrice);
                        }
                    }
                    if ((minPriceProduct == null ? false : !minPriceProduct.CustomerEntersPrice))
                    {
                        if (minPriceProduct.CallForPrice)
                        {
                            price = "0";
                        }
                        else if (!minPossiblePrice.HasValue)
                        {
                            Debug.WriteLine("Cannot calculate minPrice for product #{0}", new object[] { product.Id });
                        }
                        else
                        {
                            decimal finalPriceBase = taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                            decimal finalPrice     = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);
                            price = string.Concat(finalPrice);
                        }
                    }
                }
                str = price;
                return(str);
            }
            if (!permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
            {
                price = "0";
            }
            else if (!product.CustomerEntersPrice)
            {
                if (!product.CallForPrice)
                {
                    decimal minPossiblePrice = priceCalculationService.GetFinalPrice(product, workContext.CurrentCustomer, decimal.Zero, true, 2147483647);
                    decimal oldPriceBase     = taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                    decimal finalPriceBase   = taxService.GetProductPrice(product, minPossiblePrice, out taxRate);
                    currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, workContext.WorkingCurrency);
                    decimal          finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);
                    List <TierPrice> tierPrices = new List <TierPrice>();
                    if (product.HasTierPrices)
                    {
                        tierPrices.AddRange(TierPriceExtensions.RemoveDuplicatedQuantities(TierPriceExtensions.FilterForCustomer(TierPriceExtensions.FilterByStore((
                                                                                                                                                                       from tp in product.TierPrices
                                                                                                                                                                       orderby tp.Quantity
                                                                                                                                                                       select tp).ToList <TierPrice>(), storeContext.CurrentStore.Id), workContext.CurrentCustomer)));
                    }
                    if (tierPrices.Count <= 0)
                    {
                        flag = false;
                    }
                    else
                    {
                        flag = (tierPrices.Count != 1 ? true : tierPrices[0].Quantity > 1);
                    }
                    if (!flag)
                    {
                        price = ((finalPriceBase == oldPriceBase ? true : oldPriceBase == decimal.Zero) ? string.Concat(finalPrice) : string.Concat(finalPrice));
                    }
                    else
                    {
                        price = string.Concat(finalPrice);
                    }
                }
                else
                {
                    price = "0";
                }
            }
            str = price;
            return(str);
        }
        /// <summary>
        /// Generate a feed
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="store">Store</param>
        /// <returns>Generated feed</returns>
        public void GenerateFeed(Stream stream, Store store)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (store == null)
            {
                throw new ArgumentNullException("store");
            }

            const string googleBaseNamespace = "http://base.google.com/ns/1.0";

            var settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8
            };

            //language
            var languageId = 0;
            var languages  = _languageService.GetAllLanguages(storeId: store.Id);

            //if we have only one language, let's use it
            if (languages.Count == 1)
            {
                //let's use the first one
                var language = languages.FirstOrDefault();
                languageId = language != null ? language.Id : 0;
            }
            //otherwise, use the current one
            if (languageId == 0)
            {
                languageId = _workContext.WorkingLanguage.Id;
            }

            //we load all google products here using one SQL request (performance optimization)
            var allGoogleProducts = _googleService.GetAll();

            using (var writer = XmlWriter.Create(stream, settings))
            {
                //Generate feed according to the following specs: http://www.google.com/support/merchants/bin/answer.py?answer=188494&expand=GB
                writer.WriteStartDocument();
                writer.WriteStartElement("rss");
                writer.WriteAttributeString("version", "2.0");
                writer.WriteAttributeString("xmlns", "g", null, googleBaseNamespace);
                writer.WriteStartElement("channel");
                writer.WriteElementString("title", "Google Base feed");
                writer.WriteElementString("link", "http://base.google.com/base/");
                writer.WriteElementString("description", "Information about products");


                var products1 = _productService.SearchProducts(storeId: store.Id, visibleIndividuallyOnly: true);
                foreach (var product1 in products1)
                {
                    var productsToProcess = new List <Product>();
                    switch (product1.ProductType)
                    {
                    case ProductType.SimpleProduct:
                    {
                        //simple product doesn't have child products
                        productsToProcess.Add(product1);
                    }
                    break;

                    case ProductType.GroupedProduct:
                    {
                        //grouped products could have several child products
                        var associatedProducts = _productService.GetAssociatedProducts(product1.Id, store.Id);
                        productsToProcess.AddRange(associatedProducts);
                    }
                    break;

                    default:
                        continue;
                    }
                    foreach (var product in productsToProcess)
                    {
                        writer.WriteStartElement("item");

                        #region Basic Product Information

                        //id [id]- An identifier of the item
                        writer.WriteElementString("g", "id", googleBaseNamespace, product.Id.ToString());

                        //title [title] - Title of the item
                        writer.WriteStartElement("title");
                        var title = product.GetLocalized(x => x.Name, languageId);
                        //title should be not longer than 70 characters
                        if (title.Length > 70)
                        {
                            title = title.Substring(0, 70);
                        }
                        writer.WriteCData(title);
                        writer.WriteEndElement(); // title

                        //description [description] - Description of the item
                        writer.WriteStartElement("description");
                        string description = product.GetLocalized(x => x.FullDescription, languageId);
                        if (String.IsNullOrEmpty(description))
                        {
                            description = product.GetLocalized(x => x.ShortDescription, languageId);
                        }
                        if (String.IsNullOrEmpty(description))
                        {
                            description = product.GetLocalized(x => x.Name, languageId); //description is required
                        }
                        //resolving character encoding issues in your data feed
                        description = StripInvalidChars(description, true);
                        writer.WriteCData(description);
                        writer.WriteEndElement(); // description



                        //google product category [google_product_category] - Google's category of the item
                        //the category of the product according to Google’s product taxonomy. http://www.google.com/support/merchants/bin/answer.py?answer=160081
                        string googleProductCategory = "";
                        //var googleProduct = _googleService.GetByProductId(product.Id);
                        var googleProduct = allGoogleProducts.FirstOrDefault(x => x.ProductId == product.Id);
                        if (googleProduct != null)
                        {
                            googleProductCategory = googleProduct.Taxonomy;
                        }
                        if (String.IsNullOrEmpty(googleProductCategory))
                        {
                            googleProductCategory = _googleShoppingSettings.DefaultGoogleCategory;
                        }
                        if (String.IsNullOrEmpty(googleProductCategory))
                        {
                            throw new NopException("Default Google category is not set");
                        }
                        writer.WriteStartElement("g", "google_product_category", googleBaseNamespace);
                        writer.WriteCData(googleProductCategory);
                        writer.WriteFullEndElement(); // g:google_product_category

                        //product type [product_type] - Your category of the item
                        var defaultProductCategory = _categoryService
                                                     .GetProductCategoriesByProductId(product.Id, store.Id)
                                                     .FirstOrDefault();
                        if (defaultProductCategory != null)
                        {
                            //TODO localize categories
                            var category = defaultProductCategory.Category
                                           .GetFormattedBreadCrumb(_categoryService, separator: ">", languageId: languageId);
                            if (!String.IsNullOrEmpty((category)))
                            {
                                writer.WriteStartElement("g", "product_type", googleBaseNamespace);
                                writer.WriteCData(category);
                                writer.WriteFullEndElement(); // g:product_type
                            }
                        }

                        //link [link] - URL directly linking to your item's page on your website
                        var productUrl = string.Format("{0}{1}", store.Url, product.GetSeName(languageId));
                        writer.WriteElementString("link", productUrl);

                        //image link [image_link] - URL of an image of the item
                        //additional images [additional_image_link]
                        //up to 10 pictures
                        const int maximumPictures = 10;
                        var       pictures        = _pictureService.GetPicturesByProductId(product.Id, maximumPictures);
                        for (int i = 0; i < pictures.Count; i++)
                        {
                            var picture  = pictures[i];
                            var imageUrl = _pictureService.GetPictureUrl(picture,
                                                                         _googleShoppingSettings.ProductPictureSize,
                                                                         storeLocation: store.Url);

                            if (i == 0)
                            {
                                //default image
                                writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl);
                            }
                            else
                            {
                                //additional image
                                writer.WriteElementString("g", "additional_image_link", googleBaseNamespace, imageUrl);
                            }
                        }
                        if (!pictures.Any())
                        {
                            //no picture? submit a default one
                            var imageUrl = _pictureService.GetDefaultPictureUrl(_googleShoppingSettings.ProductPictureSize, storeLocation: store.Url);
                            writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl);
                        }

                        //condition [condition] - Condition or state of the item
                        writer.WriteElementString("g", "condition", googleBaseNamespace, "new");

                        writer.WriteElementString("g", "expiration_date", googleBaseNamespace, DateTime.Now.AddDays(_googleShoppingSettings.ExpirationNumberOfDays).ToString("yyyy-MM-dd"));

                        #endregion

                        #region Availability & Price

                        //availability [availability] - Availability status of the item
                        string availability = "in stock"; //in stock by default
                        if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                            product.GetTotalStockQuantity() <= 0)
                        {
                            availability = "out of stock";
                        }
                        //uncomment th code below in order to support "preorder" value for "availability"
                        //if (product.AvailableForPreOrder &&
                        //    (!product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                        //    product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow))
                        //{
                        //    availability = "preorder";
                        //}
                        writer.WriteElementString("g", "availability", googleBaseNamespace, availability);

                        //price [price] - Price of the item
                        var     currency = GetUsedCurrency();
                        decimal finalPriceBase;
                        if (_googleShoppingSettings.PricesConsiderPromotions)
                        {
                            var minPossiblePrice = _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer);

                            if (product.HasTierPrices)
                            {
                                //calculate price for the maximum quantity if we have tier prices, and choose minimal
                                minPossiblePrice = Math.Min(minPossiblePrice,
                                                            _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, quantity: int.MaxValue));
                            }

                            decimal taxRate;
                            finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out taxRate);
                        }
                        else
                        {
                            finalPriceBase = product.Price;
                        }
                        decimal price = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, currency);
                        //round price now so it matches the product details page
                        price = RoundingHelper.RoundPrice(price);

                        writer.WriteElementString("g", "price", googleBaseNamespace,
                                                  price.ToString(new CultureInfo("en-US", false).NumberFormat) + " " +
                                                  currency.CurrencyCode);

                        #endregion

                        #region Unique Product Identifiers

                        /* Unique product identifiers such as UPC, EAN, JAN or ISBN allow us to show your listing on the appropriate product page. If you don't provide the required unique product identifiers, your store may not appear on product pages, and all your items may be removed from Product Search.
                         * We require unique product identifiers for all products - except for custom made goods. For apparel, you must submit the 'brand' attribute. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute. In all cases, we recommend you submit all three attributes.
                         * You need to submit at least two attributes of 'brand', 'gtin' and 'mpn', but we recommend that you submit all three if available. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute, but we recommend that you include 'brand' and 'mpn' if available.
                         */



                        //brand [brand] - Brand of the item
                        var defaultDestination =
                            _destinationService.GetProductDestinationsByProductId((product.Id)).FirstOrDefault();
                        if (defaultDestination != null)
                        {
                            writer.WriteStartElement("g", "brand", googleBaseNamespace);
                            writer.WriteCData(defaultDestination.Destination.Name);
                            writer.WriteFullEndElement(); // g:brand
                        }



                        //identifier exists [identifier_exists] - Submit custom goods
                        if (googleProduct != null && googleProduct.CustomGoods)
                        {
                            writer.WriteElementString("g", "identifier_exists", googleBaseNamespace, "FALSE");
                        }

                        #endregion



                        writer.WriteEndElement(); // item
                    }
                }

                writer.WriteEndElement(); // channel
                writer.WriteEndElement(); // rss
                writer.WriteEndDocument();
            }
        }
        /// <summary>
        /// Generate a feed
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="store">Store</param>
        /// <returns>Generated feed</returns>
        public void GenerateFeed(Stream stream, Store store)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (store == null)
            {
                throw new ArgumentNullException(nameof(store));
            }

            const string googleBaseNamespace = "http://base.google.com/ns/1.0";

            var settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8
            };

            //language
            var languageId = 0;
            var languages  = _languageService.GetAllLanguages(storeId: store.Id);

            //if we have only one language, let's use it
            if (languages.Count == 1)
            {
                //let's use the first one
                var language = languages.FirstOrDefault();
                languageId = language != null ? language.Id : 0;
            }
            //otherwise, use the current one
            if (languageId == 0)
            {
                languageId = _workContext.WorkingLanguage.Id;
            }

            //we load all Google products here using one SQL request (performance optimization)
            var allGoogleProducts = _googleService.GetAll();



            //google
            GoogleWebAuthorizationBroker.Folder = "ShoppingContent.Sample";
            var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                new ClientSecrets
            {
                ClientId     = "584676283202-qphqjj998id40caks269cjag92dsc4rn.apps.googleusercontent.com",
                ClientSecret = "mv3j9LBNBKuGXjM1xLCi6Tbr"
            },
                new string[] { ShoppingContentService.Scope.Content },
                "user",
                CancellationToken.None).Result;

            // Create the service.
            var service = new ShoppingContentService(new BaseClientService.Initializer()
            {
                HttpClientInitializer = credential,
                ApplicationName       = "Shopping Content Arc",
            });



            using (var writer = XmlWriter.Create(stream, settings))
            {
                //Generate feed according to the following specs: http://www.google.com/support/merchants/bin/answer.py?answer=188494&expand=GB
                writer.WriteStartDocument();
                writer.WriteStartElement("rss");
                writer.WriteAttributeString("version", "2.0");
                writer.WriteAttributeString("xmlns", "g", null, googleBaseNamespace);
                writer.WriteStartElement("channel");
                writer.WriteElementString("title", "Google Base feed");
                writer.WriteElementString("link", "http://base.google.com/base/");
                writer.WriteElementString("description", "Information about products");


                var products1 = _productService.SearchProducts(storeId: store.Id, visibleIndividuallyOnly: true)
                                .Where(x => !x.ExcludeGoogleFeed);


                var query = from p in products1
                            from pc in p.ProductCategories.Where(pc => !pc.Category.Name.Contains("Copier") && !pc.Category.Name.Contains("Copiers - New"))
                            select p;

                foreach (var product1 in products1)
                {
                    Google.Apis.ShoppingContent.v2.Data.Product productG = new Google.Apis.ShoppingContent.v2.Data.Product();

                    var productsToProcess = new List <Core.Domain.Catalog.Product>();
                    productG.ContentLanguage       = "EN";
                    productG.TargetCountry         = "US";
                    productG.Channel               = "online";
                    productG.Availability          = "in stock";
                    productG.Condition             = "new";
                    productG.GoogleProductCategory = "Electronics > Print, Copy, Scan & Fax Accessories > Copier Accessories";
                    productG.Gtin = product1.Gtin;



                    var legacy_Reader = _dbContext.SqlQuery <string>($"SELECT LegacyCode FROM [dbo].LegacyIds where ItemID={product1.Id}").ToList();
                    if (legacy_Reader.Count > 0)
                    {
                        foreach (var id in legacy_Reader)
                        {
                            productG.Title += $" - {id}";
                        }
                    }

                    var categoryP = product1.ProductCategories.FirstOrDefault();
                    if (categoryP != null)
                    {
                        if (categoryP.Category.Name.Contains("Toner"))
                        {
                            productG.ProductType = "Electronics > Print, Copy, Scan & Fax Accessories > Printer Accessories > Toner & Inkjet Cartridges";
                        }
                        else
                        {
                            productG.ProductType = "Electronics > Print, Copy, Scan & Fax Accessories";
                        }
                    }



                    switch (product1.ProductType)
                    {
                    case ProductType.SimpleProduct:
                    {
                        //simple product doesn't have child products
                        productsToProcess.Add(product1);
                    }
                    break;

                    case ProductType.GroupedProduct:
                    {
                        //grouped products could have several child products
                        var associatedProducts = _productService.GetAssociatedProducts(product1.Id, store.Id);
                        productsToProcess.AddRange(associatedProducts);
                    }
                    break;

                    default:
                        continue;
                    }
                    foreach (var product in productsToProcess)
                    {
                        writer.WriteStartElement("item");

                        #region Basic Product Information

                        //id [id]- An identifier of the item
                        writer.WriteElementString("g", "id", googleBaseNamespace, product.Id.ToString());

                        //title [title] - Title of the item
                        writer.WriteStartElement("title");
                        var title = product.GetLocalized(x => x.Name, languageId);
                        //title should be not longer than 70 characters
                        if (title.Length > 70)
                        {
                            title = title.Substring(0, 70);
                        }
                        writer.WriteCData(title);
                        writer.WriteEndElement(); // title

                        //description [description] - Description of the item
                        writer.WriteStartElement("description");
                        string description = product.GetLocalized(x => x.FullDescription, languageId);
                        if (String.IsNullOrEmpty(description))
                        {
                            description = product.GetLocalized(x => x.ShortDescription, languageId);
                        }
                        if (String.IsNullOrEmpty(description))
                        {
                            description = product.GetLocalized(x => x.Name, languageId); //description is required
                        }
                        //resolving character encoding issues in your data feed
                        description = StripInvalidChars(description, true);
                        writer.WriteCData(description);
                        writer.WriteEndElement(); // description



                        //google product category [google_product_category] - Google's category of the item
                        //the category of the product according to Google’s product taxonomy. http://www.google.com/support/merchants/bin/answer.py?answer=160081
                        string googleProductCategory = "";
                        //var googleProduct = _googleService.GetByProductId(product.Id);
                        var googleProduct = allGoogleProducts.FirstOrDefault(x => x.ProductId == product.Id);
                        if (googleProduct != null)
                        {
                            googleProductCategory = googleProduct.Taxonomy;
                        }
                        if (String.IsNullOrEmpty(googleProductCategory))
                        {
                            googleProductCategory = _googleShoppingSettings.DefaultGoogleCategory;
                        }
                        if (String.IsNullOrEmpty(googleProductCategory))
                        {
                            throw new NopException("Default Google category is not set");
                        }
                        writer.WriteStartElement("g", "google_product_category", googleBaseNamespace);
                        writer.WriteCData(googleProductCategory);
                        writer.WriteFullEndElement(); // g:google_product_category

                        //product type [product_type] - Your category of the item
                        var defaultProductCategory = _categoryService
                                                     .GetProductCategoriesByProductId(product.Id, store.Id)
                                                     .FirstOrDefault();
                        if (defaultProductCategory != null)
                        {
                            //TODO localize categories
                            var category = defaultProductCategory.Category
                                           .GetFormattedBreadCrumb(_categoryService, separator: ">", languageId: languageId);
                            if (!String.IsNullOrEmpty(category))
                            {
                                writer.WriteStartElement("g", "product_type", googleBaseNamespace);
                                writer.WriteCData(category);
                                writer.WriteFullEndElement(); // g:product_type
                            }
                        }

                        //link [link] - URL directly linking to your item's page on your website
                        var productUrl = GetUrlHelper().RouteUrl("Product", new { SeName = product.GetSeName(languageId) }, GetHttpProtocol());

                        productG.Link = productUrl;

                        writer.WriteElementString("link", productUrl);

                        //image link [image_link] - URL of an image of the item
                        //additional images [additional_image_link]
                        //up to 10 pictures
                        const int maximumPictures = 10;
                        var       storeLocation   = _securitySettings.ForceSslForAllPages ?
                                                    (!string.IsNullOrWhiteSpace(store.SecureUrl) ? store.SecureUrl : store.Url.Replace("http://", "https://")):
                                                    store.Url;
                        var pictures = _pictureService.GetPicturesByProductId(product.Id, maximumPictures);
                        for (int i = 0; i < pictures.Count; i++)
                        {
                            var picture  = pictures[i];
                            var imageUrl = _pictureService.GetPictureUrl(picture,
                                                                         _googleShoppingSettings.ProductPictureSize,
                                                                         storeLocation: storeLocation);

                            if (i == 0)
                            {
                                //default image

                                productG.ImageLink = imageUrl;

                                writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl);
                            }
                            else
                            {
                                //additional image

                                productG.AdditionalImageLinks.Add(imageUrl);

                                writer.WriteElementString("g", "additional_image_link", googleBaseNamespace, imageUrl);
                            }
                        }
                        if (!pictures.Any())
                        {
                            //no picture? submit a default one
                            var imageUrl = _pictureService.GetDefaultPictureUrl(_googleShoppingSettings.ProductPictureSize, storeLocation: storeLocation);

                            productG.ImageLink = imageUrl;

                            writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl);
                        }

                        //condition [condition] - Condition or state of the item

                        productG.Condition      = "new";
                        productG.ExpirationDate = DateTime.Now.AddDays(_googleShoppingSettings.ExpirationNumberOfDays).ToString("yyyy-MM-dd");

                        writer.WriteElementString("g", "condition", googleBaseNamespace, "new");

                        writer.WriteElementString("g", "expiration_date", googleBaseNamespace, DateTime.Now.AddDays(_googleShoppingSettings.ExpirationNumberOfDays).ToString("yyyy-MM-dd"));

                        #endregion

                        #region Availability & Price

                        //availability [availability] - Availability status of the item
                        string availability = "in stock"; //in stock by default
                        if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                            product.BackorderMode == BackorderMode.NoBackorders &&
                            product.GetTotalStockQuantity() <= 0)
                        {
                            availability = "out of stock";
                        }
                        //uncomment th code below in order to support "preorder" value for "availability"
                        //if (product.AvailableForPreOrder &&
                        //    (!product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                        //    product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow))
                        //{
                        //    availability = "preorder";
                        //}

                        productG.Availability = availability;

                        writer.WriteElementString("g", "availability", googleBaseNamespace, availability);

                        //price [price] - Price of the item
                        var     currency = GetUsedCurrency();
                        decimal finalPriceBase;
                        if (_googleShoppingSettings.PricesConsiderPromotions)
                        {
                            var minPossiblePrice = _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer);

                            if (product.HasTierPrices)
                            {
                                //calculate price for the maximum quantity if we have tier prices, and choose minimal
                                minPossiblePrice = Math.Min(minPossiblePrice,
                                                            _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, quantity: int.MaxValue));
                            }

                            finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out decimal _);
                        }
                        else
                        {
                            finalPriceBase = product.Price;
                        }
                        decimal price = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, currency);
                        //round price now so it matches the product details page
                        price = RoundingHelper.RoundPrice(price);

                        Price priceG = new Price {
                            Currency = currency.CurrencyCode, Value = price.ToString(new CultureInfo("en-US", false).NumberFormat)
                        };

                        productG.Price = priceG;

                        writer.WriteElementString("g", "price", googleBaseNamespace,
                                                  price.ToString(new CultureInfo("en-US", false).NumberFormat) + " " +
                                                  currency.CurrencyCode);

                        #endregion

                        #region Unique Product Identifiers

                        /* Unique product identifiers such as UPC, EAN, JAN or ISBN allow us to show your listing on the appropriate product page. If you don't provide the required unique product identifiers, your store may not appear on product pages, and all your items may be removed from Product Search.
                         * We require unique product identifiers for all products - except for custom made goods. For apparel, you must submit the 'brand' attribute. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute. In all cases, we recommend you submit all three attributes.
                         * You need to submit at least two attributes of 'brand', 'gtin' and 'mpn', but we recommend that you submit all three if available. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute, but we recommend that you include 'brand' and 'mpn' if available.
                         */

                        //GTIN [gtin] - GTIN
                        var gtin = product.Gtin;
                        if (!String.IsNullOrEmpty(gtin))
                        {
                            productG.Gtin = gtin;

                            writer.WriteStartElement("g", "gtin", googleBaseNamespace);
                            writer.WriteCData(gtin);
                            writer.WriteFullEndElement(); // g:gtin
                        }

                        //brand [brand] - Brand of the item
                        var defaultManufacturer =
                            _manufacturerService.GetProductManufacturersByProductId((product.Id)).FirstOrDefault();
                        if (defaultManufacturer != null)
                        {
                            productG.Brand = defaultManufacturer.Manufacturer.Name;

                            writer.WriteStartElement("g", "brand", googleBaseNamespace);
                            writer.WriteCData(defaultManufacturer.Manufacturer.Name);
                            writer.WriteFullEndElement(); // g:brand
                        }


                        //mpn [mpn] - Manufacturer Part Number (MPN) of the item
                        var mpn = product.ManufacturerPartNumber;
                        if (!String.IsNullOrEmpty(mpn))
                        {
                            productG.Mpn = mpn;

                            writer.WriteStartElement("g", "mpn", googleBaseNamespace);
                            writer.WriteCData(mpn);
                            writer.WriteFullEndElement(); // g:mpn
                        }

                        //identifier exists [identifier_exists] - Submit custom goods
                        if (googleProduct != null && googleProduct.CustomGoods)
                        {
                            productG.IdentifierExists = false;

                            writer.WriteElementString("g", "identifier_exists", googleBaseNamespace, "FALSE");
                        }

                        #endregion

                        #region Apparel Products

                        /* Apparel includes all products that fall under 'Apparel & Accessories' (including all sub-categories)
                         * in Google’s product taxonomy.
                         */

                        //gender [gender] - Gender of the item
                        if (googleProduct != null && !String.IsNullOrEmpty(googleProduct.Gender))
                        {
                            productG.Gender = googleProduct.Gender;

                            writer.WriteStartElement("g", "gender", googleBaseNamespace);
                            writer.WriteCData(googleProduct.Gender);
                            writer.WriteFullEndElement(); // g:gender
                        }

                        //age group [age_group] - Target age group of the item
                        if (googleProduct != null && !String.IsNullOrEmpty(googleProduct.AgeGroup))
                        {
                            productG.AgeGroup = googleProduct.AgeGroup;

                            writer.WriteStartElement("g", "age_group", googleBaseNamespace);
                            writer.WriteCData(googleProduct.AgeGroup);
                            writer.WriteFullEndElement(); // g:age_group
                        }

                        //color [color] - Color of the item
                        if (googleProduct != null && !String.IsNullOrEmpty(googleProduct.Color))
                        {
                            productG.Color = googleProduct.Color;

                            writer.WriteStartElement("g", "color", googleBaseNamespace);
                            writer.WriteCData(googleProduct.Color);
                            writer.WriteFullEndElement(); // g:color
                        }

                        //size [size] - Size of the item
                        if (googleProduct != null && !String.IsNullOrEmpty(googleProduct.Size))
                        {
                            productG.Sizes.Add(googleProduct.Size);

                            writer.WriteStartElement("g", "size", googleBaseNamespace);
                            writer.WriteCData(googleProduct.Size);
                            writer.WriteFullEndElement(); // g:size
                        }

                        #endregion

                        #region Tax & Shipping

                        //tax [tax]
                        //The tax attribute is an item-level override for merchant-level tax settings as defined in your Google Merchant Center account. This attribute is only accepted in the US, if your feed targets a country outside of the US, please do not use this attribute.
                        //IMPORTANT NOTE: Set tax in your Google Merchant Center account settings

                        //IMPORTANT NOTE: Set shipping in your Google Merchant Center account settings

                        //shipping weight [shipping_weight] - Weight of the item for shipping
                        //We accept only the following units of weight: lb, oz, g, kg.
                        if (_googleShoppingSettings.PassShippingInfoWeight)
                        {
                            string weightName;
                            var    shippingWeight   = product.Weight;
                            var    weightSystemName = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword;
                            switch (weightSystemName)
                            {
                            case "ounce":
                                weightName = "oz";
                                break;

                            case "lb":
                                weightName = "lb";
                                break;

                            case "grams":
                                weightName = "g";
                                break;

                            case "kg":
                                weightName = "kg";
                                break;

                            default:
                                //unknown weight
                                throw new Exception("Not supported weight. Google accepts the following units: lb, oz, g, kg.");
                            }
                            ProductShippingDimension psd = new ProductShippingDimension
                            {
                                Unit  = weightName,
                                Value = double.Parse(shippingWeight.ToString())
                            };

                            productG.ShippingHeight = psd;

                            writer.WriteElementString("g", "shipping_weight", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", shippingWeight.ToString(new CultureInfo("en-US", false).NumberFormat), weightName));
                        }

                        //shipping length [shipping_length] - Length of the item for shipping
                        //shipping width [shipping_width] - Width of the item for shipping
                        //shipping height [shipping_height] - Height of the item for shipping
                        //We accept only the following units of length: in, cm
                        if (_googleShoppingSettings.PassShippingInfoDimensions)
                        {
                            string dimensionName;
                            var    length = product.Length;
                            var    width  = product.Width;
                            var    height = product.Height;
                            var    dimensionSystemName = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).SystemKeyword;
                            switch (dimensionSystemName)
                            {
                            case "inches":
                                dimensionName = "in";
                                break;

                            //TODO support other dimensions (convert to cm)
                            default:
                                //unknown dimension
                                throw new Exception("Not supported dimension. Google accepts the following units: in, cm.");
                            }

                            ProductShippingDimension psd = new ProductShippingDimension
                            {
                                Unit  = dimensionName,
                                Value = double.Parse(length.ToString())
                            };
                            productG.ShippingLength = psd;

                            psd = new ProductShippingDimension
                            {
                                Unit  = dimensionName,
                                Value = double.Parse(width.ToString())
                            };
                            productG.ShippingWidth = psd;

                            psd = new ProductShippingDimension
                            {
                                Unit  = dimensionName,
                                Value = double.Parse(height.ToString())
                            };
                            productG.ShippingHeight = psd;

                            writer.WriteElementString("g", "shipping_length", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", length.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName));
                            writer.WriteElementString("g", "shipping_width", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", width.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName));
                            writer.WriteElementString("g", "shipping_height", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", height.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName));
                        }

                        #endregion

                        writer.WriteEndElement(); // item


                        //used in in description
                        string usedinquery = $@"SELECT     ItemsCompatability.ItemID 
                        FROM         ItemsCompatability INNER JOIN
                                              Items ON ItemsCompatability.ItemID = Items.ItemID
                        WHERE     (ItemsCompatability.ItemIDPart ={product.Id})
                        UNION
                        SELECT     [Groups-Items].ItemID 
                        FROM         [Groups-Items] INNER JOIN
                                              Items AS Items_1 ON [Groups-Items].ItemID = Items_1.ItemID
                        WHERE     ([Groups-Items].GroupID IN
                                                  (SELECT     GroupID
                                                    FROM          [Relations-Groups-Items]
                                                    WHERE      (ItemID ={product.Id}) AND (Direction = 'B')))
                        UNION
                        SELECT     [Relations-Groups-Items].ItemID 
                        FROM         Items INNER JOIN
                                              [Relations-Groups-Items] ON Items.ItemID = [Relations-Groups-Items].ItemID
                        WHERE     ([Relations-Groups-Items].Direction = 'A') AND ([Relations-Groups-Items].GroupID IN
                                                  (SELECT     GroupID
                                                    FROM          [Groups-Items]
                                                    WHERE      (ItemID ={product.Id})))";


                        var usedin_Reader = _dbContext.SqlQuery <int>(usedinquery).ToList();
                        if (usedin_Reader.Count > 0)
                        {
                            var usedIn = _productService.GetProductsByIds(usedin_Reader.ToArray());

                            foreach (var item in usedIn)
                            {
                                productG.Description = $"{productG.Description} {item.Name}, ";
                            }
                            productG.Description  = productG.Description.TrimEnd(',');
                            productG.Description += ".";
                        }
                        else
                        {
                            productG.Description += "N/A";
                        }
                    }
                }

                writer.WriteEndElement(); // channel
                writer.WriteEndElement(); // rss
                writer.WriteEndDocument();
            }
        }
示例#20
0
        public void CanGetFinalProductPrice()
        {
            var product = _productService.GetProductBySku("BP_20_WSP");

            //customer
            var customer = new Customer();

            _priceCalcService.GetFinalPrice(product, customer, 0, false).Should().Be(79.99M);
            _priceCalcService.GetFinalPrice(product, customer, 0, false, 2).Should().Be(19M);
        }
示例#21
0
        protected IEnumerable <ProductOverviewModel> PrepareProductOverviewModels(IEnumerable <Product> products,
                                                                                  bool preparePriceModel                 = true, bool preparePictureModel = true,
                                                                                  int?productThumbPictureSize            = null, bool prepareSpecificationAttributes = false,
                                                                                  bool forceRedirectionAfterAddingToCart = false)
        {
            if (products == null)
            {
                throw new ArgumentNullException("products");
            }

            var models = new List <ProductOverviewModel>();

            foreach (var product in products)
            {
                var model = new ProductOverviewModel()
                {
                    Id               = product.Id,
                    Name             = product.GetLocalized(x => x.Name),
                    ShortDescription = product.GetLocalized(x => x.ShortDescription),
                    FullDescription  = product.GetLocalized(x => x.FullDescription),
                    SeName           = product.GetSeName(),
                };
                //price
                if (preparePriceModel)
                {
                    #region Prepare product price

                    var priceModel = new ProductOverviewModel.ProductPriceModel();

                    switch (product.ProductType)
                    {
                    case ProductType.GroupedProduct:
                    {
                        #region Grouped product

                        var associatedProducts = _productService.GetAssociatedProducts(product.Id, _storeContext.CurrentStore.Id);

                        switch (associatedProducts.Count)
                        {
                        case 0:
                        {
                            //no associated products
                            priceModel.OldPrice              = null;
                            priceModel.Price                 = null;
                            priceModel.DisableBuyButton      = true;
                            priceModel.DisableWishlistButton = true;
                            priceModel.AvailableForPreOrder  = false;
                        }
                        break;

                        default:
                        {
                            //we have at least one associated product
                            priceModel.DisableBuyButton      = true;
                            priceModel.DisableWishlistButton = true;
                            priceModel.AvailableForPreOrder  = false;

                            if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                            {
                                //find a minimum possible price
                                decimal?minPossiblePrice = null;
                                Product minPriceProduct  = null;
                                foreach (var associatedProduct in associatedProducts)
                                {
                                    //calculate for the maximum quantity (in case if we have tier prices)
                                    var tmpPrice = _priceCalculationService.GetFinalPrice(associatedProduct,
                                                                                          _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                                    if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                    {
                                        minPriceProduct  = associatedProduct;
                                        minPossiblePrice = tmpPrice;
                                    }
                                }
                                if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                                {
                                    if (minPriceProduct.CallForPrice)
                                    {
                                        priceModel.OldPrice = null;
                                        priceModel.Price    = _localizationService.GetResource("Products.CallForPrice");
                                    }
                                    else if (minPossiblePrice.HasValue)
                                    {
                                        //calculate prices
                                        decimal taxRate        = decimal.Zero;
                                        decimal finalPriceBase = _taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                                        decimal finalPrice     = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _workContext.WorkingCurrency);

                                        priceModel.OldPrice = null;
                                        priceModel.Price    = String.Format(_localizationService.GetResource("Products.PriceRangeFrom"), _priceFormatter.FormatPrice(finalPrice));
                                    }
                                    else
                                    {
                                        //Actually it's not possible (we presume that minimalPrice always has a value)
                                        //We never should get here
                                        Debug.WriteLine(string.Format("Cannot calculate minPrice for product #{0}", product.Id));
                                    }
                                }
                            }
                            else
                            {
                                //hide prices
                                priceModel.OldPrice = null;
                                priceModel.Price    = null;
                            }
                        }
                        break;
                        }

                        #endregion
                    }
                    break;

                    case ProductType.SimpleProduct:
                    default:
                    {
                        #region Simple product

                        //add to cart button
                        priceModel.DisableBuyButton = product.DisableBuyButton ||
                                                      !_permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                                      !_permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                        //add to wishlist button
                        priceModel.DisableWishlistButton = product.DisableWishlistButton ||
                                                           !_permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                                           !_permissionService.Authorize(StandardPermissionProvider.DisplayPrices);
                        //pre-order
                        if (product.AvailableForPreOrder)
                        {
                            priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                                              product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                            priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                        }

                        //prices
                        if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                        {
                            //calculate for the maximum quantity (in case if we have tier prices)
                            decimal minPossiblePrice = _priceCalculationService.GetFinalPrice(product,
                                                                                              _workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                            if (!product.CustomerEntersPrice)
                            {
                                if (product.CallForPrice)
                                {
                                    //call for price
                                    priceModel.OldPrice = null;
                                    priceModel.Price    = _localizationService.GetResource("Products.CallForPrice");
                                }
                                else
                                {
                                    //calculate prices
                                    decimal taxRate        = decimal.Zero;
                                    decimal oldPriceBase   = _taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                                    decimal finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out taxRate);

                                    decimal oldPrice   = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency);
                                    decimal finalPrice = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, _workContext.WorkingCurrency);

                                    //do we have tier prices configured?
                                    var tierPrices = new List <TierPrice>();
                                    if (product.HasTierPrices)
                                    {
                                        tierPrices.AddRange(product.TierPrices
                                                            .OrderBy(tp => tp.Quantity)
                                                            .ToList()
                                                            .FilterByStore(_storeContext.CurrentStore.Id)
                                                            .FilterForCustomer(_workContext.CurrentCustomer)
                                                            .RemoveDuplicatedQuantities());
                                    }
                                    //When there is just one tier (with  qty 1),
                                    //there are no actual savings in the list.
                                    bool displayFromMessage = tierPrices.Count > 0 &&
                                                              !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                                    if (displayFromMessage)
                                    {
                                        priceModel.OldPrice = null;
                                        priceModel.Price    = String.Format(_localizationService.GetResource("Products.PriceRangeFrom"), _priceFormatter.FormatPrice(finalPrice));
                                    }
                                    else
                                    {
                                        if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                        {
                                            priceModel.OldPrice = _priceFormatter.FormatPrice(oldPrice);
                                            priceModel.Price    = _priceFormatter.FormatPrice(finalPrice);
                                        }
                                        else
                                        {
                                            priceModel.OldPrice = null;
                                            priceModel.Price    = _priceFormatter.FormatPrice(finalPrice);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            //hide prices
                            priceModel.OldPrice = null;
                            priceModel.Price    = null;
                        }

                        #endregion
                    }
                    break;
                    }

                    model.ProductPrice = priceModel;

                    #endregion
                }

                //picture
                if (preparePictureModel)
                {
                    #region Prepare product picture

                    //If a size has been set in the view, we use it in priority
                    int pictureSize = productThumbPictureSize.HasValue ? productThumbPictureSize.Value : 125;
                    //prepare picture model
                    var picture = _pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
                    model.DefaultPictureModel = new PictureModel()
                    {
                        ImageUrl         = _pictureService.GetPictureUrl(picture, pictureSize),
                        FullSizeImageUrl = _pictureService.GetPictureUrl(picture),
                        Title            = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name),
                        AlternateText    = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name)
                    };
                    #endregion
                }

                models.Add(model);
            }
            return(models);
        }
示例#22
0
        /// <summary>
        /// Generate a feed
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="store">Store</param>
        /// <returns>Generated feed</returns>
        public void GenerateFeed(Stream stream, Store store)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (store == null)
            {
                throw new ArgumentNullException(nameof(store));
            }

            const string googleBaseNamespace = "http://base.google.com/ns/1.0";

            var settings = new XmlWriterSettings
            {
                Encoding = Encoding.UTF8
            };

            var googleShoppingSettings = _settingService.LoadSetting <GoogleShoppingSettings>(store.Id);

            //language
            var languageId = 0;
            var languages  = _languageService.GetAllLanguages(storeId: store.Id);

            //if we have only one language, let's use it
            if (languages.Count == 1)
            {
                //let's use the first one
                var language = languages.FirstOrDefault();
                languageId = language != null ? language.Id : 0;
            }
            //otherwise, use the current one
            if (languageId == 0)
            {
                languageId = _workContext.WorkingLanguage.Id;
            }

            //we load all Google products here using one SQL request (performance optimization)
            var allGoogleProducts = _googleService.GetAll();

            using (var writer = XmlWriter.Create(stream, settings))
            {
                //Generate feed according to the following specs: http://www.google.com/support/merchants/bin/answer.py?answer=188494&expand=GB
                writer.WriteStartDocument();
                writer.WriteStartElement("rss");
                writer.WriteAttributeString("version", "2.0");
                writer.WriteAttributeString("xmlns", "g", null, googleBaseNamespace);
                writer.WriteStartElement("channel");
                writer.WriteElementString("title", "Google Base feed");
                writer.WriteElementString("link", "http://base.google.com/base/");
                writer.WriteElementString("description", "Information about products");

                var products1 = _productService.SearchProducts(storeId: store.Id, visibleIndividuallyOnly: true);
                foreach (var product1 in products1)
                {
                    var productsToProcess = new List <Product>();
                    switch (product1.ProductType)
                    {
                    case ProductType.SimpleProduct:
                    {
                        //simple product doesn't have child products
                        productsToProcess.Add(product1);
                    }
                    break;

                    case ProductType.GroupedProduct:
                    {
                        //grouped products could have several child products
                        var associatedProducts = _productService.GetAssociatedProducts(product1.Id, store.Id);
                        productsToProcess.AddRange(associatedProducts);
                    }
                    break;

                    default:
                        continue;
                    }
                    foreach (var product in productsToProcess)
                    {
                        writer.WriteStartElement("item");

                        #region Basic Product Information

                        //id [id]- An identifier of the item
                        writer.WriteElementString("g", "id", googleBaseNamespace, product.Id.ToString());

                        //title [title] - Title of the item
                        writer.WriteStartElement("title");
                        var title = _localizationService.GetLocalized(product, x => x.Name, languageId);
                        //title should be not longer than 70 characters
                        if (title.Length > 70)
                        {
                            title = title.Substring(0, 70);
                        }
                        writer.WriteCData(title);
                        writer.WriteEndElement(); // title

                        //description [description] - Description of the item
                        writer.WriteStartElement("description");
                        var description = _localizationService.GetLocalized(product, x => x.FullDescription, languageId);
                        if (string.IsNullOrEmpty(description))
                        {
                            description = _localizationService.GetLocalized(product, x => x.ShortDescription, languageId);
                        }
                        if (string.IsNullOrEmpty(description))
                        {
                            description = _localizationService.GetLocalized(product, x => x.Name, languageId); //description is required
                        }
                        //resolving character encoding issues in your data feed
                        description = StripInvalidChars(description, true);
                        writer.WriteCData(description);
                        writer.WriteEndElement(); // description

                        //google product category [google_product_category] - Google's category of the item
                        //the category of the product according to Google’s product taxonomy. http://www.google.com/support/merchants/bin/answer.py?answer=160081
                        var googleProductCategory = "";
                        //var googleProduct = _googleService.GetByProductId(product.Id);
                        var googleProduct = allGoogleProducts.FirstOrDefault(x => x.ProductId == product.Id);
                        if (googleProduct != null)
                        {
                            googleProductCategory = googleProduct.Taxonomy;
                        }
                        if (string.IsNullOrEmpty(googleProductCategory))
                        {
                            googleProductCategory = googleShoppingSettings.DefaultGoogleCategory;
                        }
                        if (string.IsNullOrEmpty(googleProductCategory))
                        {
                            throw new NopException("Default Google category is not set");
                        }
                        writer.WriteStartElement("g", "google_product_category", googleBaseNamespace);
                        writer.WriteCData(googleProductCategory);
                        writer.WriteFullEndElement(); // g:google_product_category

                        //product type [product_type] - Your category of the item
                        var defaultProductCategory = _categoryService
                                                     .GetProductCategoriesByProductId(product.Id, store.Id)
                                                     .FirstOrDefault();
                        if (defaultProductCategory != null)
                        {
                            //TODO localize categories
                            var category = _categoryService.GetFormattedBreadCrumb(defaultProductCategory.Category, separator: ">", languageId: languageId);
                            if (!string.IsNullOrEmpty(category))
                            {
                                writer.WriteStartElement("g", "product_type", googleBaseNamespace);
                                writer.WriteCData(category);
                                writer.WriteFullEndElement(); // g:product_type
                            }
                        }

                        //link [link] - URL directly linking to your item's page on your website
                        var productUrl = GetUrlHelper().RouteUrl("Product", new { SeName = _urlRecordService.GetSeName(product) }, GetHttpProtocol());
                        writer.WriteElementString("link", productUrl);

                        //image link [image_link] - URL of an image of the item
                        //additional images [additional_image_link]
                        //up to 10 pictures
                        const int maximumPictures = 10;
                        var       storeLocation   = _webHelper.GetStoreLocation(_securitySettings.ForceSslForAllPages);
                        var       pictures        = _pictureService.GetPicturesByProductId(product.Id, maximumPictures);
                        for (var i = 0; i < pictures.Count; i++)
                        {
                            var picture  = pictures[i];
                            var imageUrl = _pictureService.GetPictureUrl(picture,
                                                                         googleShoppingSettings.ProductPictureSize,
                                                                         storeLocation: storeLocation);

                            if (i == 0)
                            {
                                //default image
                                writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl);
                            }
                            else
                            {
                                //additional image
                                writer.WriteElementString("g", "additional_image_link", googleBaseNamespace, imageUrl);
                            }
                        }
                        if (!pictures.Any())
                        {
                            //no picture? submit a default one
                            var imageUrl = _pictureService.GetDefaultPictureUrl(googleShoppingSettings.ProductPictureSize, storeLocation: storeLocation);
                            writer.WriteElementString("g", "image_link", googleBaseNamespace, imageUrl);
                        }

                        //condition [condition] - Condition or state of the item
                        writer.WriteElementString("g", "condition", googleBaseNamespace, "new");

                        writer.WriteElementString("g", "expiration_date", googleBaseNamespace, DateTime.Now.AddDays(googleShoppingSettings.ExpirationNumberOfDays).ToString("yyyy-MM-dd"));

                        #endregion

                        #region Availability & Price

                        //availability [availability] - Availability status of the item
                        var availability = "in stock"; //in stock by default
                        if (product.ManageInventoryMethod == ManageInventoryMethod.ManageStock &&
                            product.BackorderMode == BackorderMode.NoBackorders &&
                            _productService.GetTotalStockQuantity(product) <= 0)
                        {
                            availability = "out of stock";
                        }
                        //uncomment th code below in order to support "preorder" value for "availability"
                        //if (product.AvailableForPreOrder &&
                        //    (!product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                        //    product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow))
                        //{
                        //    availability = "preorder";
                        //}
                        writer.WriteElementString("g", "availability", googleBaseNamespace, availability);

                        //price [price] - Price of the item
                        var     currency = GetUsedCurrency();
                        decimal finalPriceBase;
                        if (googleShoppingSettings.PricesConsiderPromotions)
                        {
                            var minPossiblePrice = _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer);

                            if (product.HasTierPrices)
                            {
                                //calculate price for the maximum quantity if we have tier prices, and choose minimal
                                minPossiblePrice = Math.Min(minPossiblePrice,
                                                            _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, quantity: int.MaxValue));
                            }

                            finalPriceBase = _taxService.GetProductPrice(product, minPossiblePrice, out var _);
                        }
                        else
                        {
                            finalPriceBase = product.Price;
                        }
                        var price = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, currency);
                        //round price now so it matches the product details page
                        price = _priceCalculationService.RoundPrice(price);

                        writer.WriteElementString("g", "price", googleBaseNamespace,
                                                  price.ToString(new CultureInfo("en-US", false).NumberFormat) + " " +
                                                  currency.CurrencyCode);

                        #endregion

                        #region Unique Product Identifiers

                        /* Unique product identifiers such as UPC, EAN, JAN or ISBN allow us to show your listing on the appropriate product page. If you don't provide the required unique product identifiers, your store may not appear on product pages, and all your items may be removed from Product Search.
                         * We require unique product identifiers for all products - except for custom made goods. For apparel, you must submit the 'brand' attribute. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute. In all cases, we recommend you submit all three attributes.
                         * You need to submit at least two attributes of 'brand', 'gtin' and 'mpn', but we recommend that you submit all three if available. For media (such as books, movies, music and video games), you must submit the 'gtin' attribute, but we recommend that you include 'brand' and 'mpn' if available.
                         */

                        //GTIN [gtin] - GTIN
                        var gtin = product.Gtin;
                        if (!string.IsNullOrEmpty(gtin))
                        {
                            writer.WriteStartElement("g", "gtin", googleBaseNamespace);
                            writer.WriteCData(gtin);
                            writer.WriteFullEndElement(); // g:gtin
                        }

                        //brand [brand] - Brand of the item
                        var defaultManufacturer = _manufacturerService.GetProductManufacturersByProductId(product.Id).FirstOrDefault();
                        if (defaultManufacturer != null)
                        {
                            writer.WriteStartElement("g", "brand", googleBaseNamespace);
                            writer.WriteCData(defaultManufacturer.Manufacturer.Name);
                            writer.WriteFullEndElement(); // g:brand
                        }

                        //mpn [mpn] - Manufacturer Part Number (MPN) of the item
                        var mpn = product.ManufacturerPartNumber;
                        if (!string.IsNullOrEmpty(mpn))
                        {
                            writer.WriteStartElement("g", "mpn", googleBaseNamespace);
                            writer.WriteCData(mpn);
                            writer.WriteFullEndElement(); // g:mpn
                        }

                        //identifier exists [identifier_exists] - Submit custom goods
                        if (googleProduct != null && googleProduct.CustomGoods)
                        {
                            writer.WriteElementString("g", "identifier_exists", googleBaseNamespace, "FALSE");
                        }

                        #endregion

                        #region Apparel Products

                        /* Apparel includes all products that fall under 'Apparel & Accessories' (including all sub-categories)
                         * in Google’s product taxonomy.
                         */

                        //gender [gender] - Gender of the item
                        if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.Gender))
                        {
                            writer.WriteStartElement("g", "gender", googleBaseNamespace);
                            writer.WriteCData(googleProduct.Gender);
                            writer.WriteFullEndElement(); // g:gender
                        }

                        //age group [age_group] - Target age group of the item
                        if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.AgeGroup))
                        {
                            writer.WriteStartElement("g", "age_group", googleBaseNamespace);
                            writer.WriteCData(googleProduct.AgeGroup);
                            writer.WriteFullEndElement(); // g:age_group
                        }

                        //color [color] - Color of the item
                        if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.Color))
                        {
                            writer.WriteStartElement("g", "color", googleBaseNamespace);
                            writer.WriteCData(googleProduct.Color);
                            writer.WriteFullEndElement(); // g:color
                        }

                        //size [size] - Size of the item
                        if (googleProduct != null && !string.IsNullOrEmpty(googleProduct.Size))
                        {
                            writer.WriteStartElement("g", "size", googleBaseNamespace);
                            writer.WriteCData(googleProduct.Size);
                            writer.WriteFullEndElement(); // g:size
                        }

                        #endregion

                        #region Tax & Shipping

                        //tax [tax]
                        //The tax attribute is an item-level override for merchant-level tax settings as defined in your Google Merchant Center account. This attribute is only accepted in the US, if your feed targets a country outside of the US, please do not use this attribute.
                        //IMPORTANT NOTE: Set tax in your Google Merchant Center account settings

                        //IMPORTANT NOTE: Set shipping in your Google Merchant Center account settings

                        //shipping weight [shipping_weight] - Weight of the item for shipping
                        //We accept only the following units of weight: lb, oz, g, kg.
                        if (googleShoppingSettings.PassShippingInfoWeight)
                        {
                            string weightName;
                            var    shippingWeight   = product.Weight;
                            var    weightSystemName = _measureService.GetMeasureWeightById(_measureSettings.BaseWeightId).SystemKeyword;
                            switch (weightSystemName)
                            {
                            case "ounce":
                                weightName = "oz";
                                break;

                            case "lb":
                                weightName = "lb";
                                break;

                            case "grams":
                                weightName = "g";
                                break;

                            case "kg":
                                weightName = "kg";
                                break;

                            default:
                                //unknown weight
                                throw new Exception("Not supported weight. Google accepts the following units: lb, oz, g, kg.");
                            }
                            writer.WriteElementString("g", "shipping_weight", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", shippingWeight.ToString(new CultureInfo("en-US", false).NumberFormat), weightName));
                        }

                        //shipping length [shipping_length] - Length of the item for shipping
                        //shipping width [shipping_width] - Width of the item for shipping
                        //shipping height [shipping_height] - Height of the item for shipping
                        //We accept only the following units of length: in, cm
                        if (googleShoppingSettings.PassShippingInfoDimensions)
                        {
                            string dimensionName;
                            var    length = product.Length;
                            var    width  = product.Width;
                            var    height = product.Height;
                            var    dimensionSystemName = _measureService.GetMeasureDimensionById(_measureSettings.BaseDimensionId).SystemKeyword;
                            switch (dimensionSystemName)
                            {
                            case "inches":
                                dimensionName = "in";
                                break;

                            //TODO support other dimensions (convert to cm)
                            default:
                                //unknown dimension
                                throw new Exception("Not supported dimension. Google accepts the following units: in, cm.");
                            }
                            writer.WriteElementString("g", "shipping_length", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", length.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName));
                            writer.WriteElementString("g", "shipping_width", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", width.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName));
                            writer.WriteElementString("g", "shipping_height", googleBaseNamespace, string.Format(CultureInfo.InvariantCulture, "{0} {1}", height.ToString(new CultureInfo("en-US", false).NumberFormat), dimensionName));
                        }

                        #endregion

                        writer.WriteEndElement(); // item
                    }
                }

                writer.WriteEndElement(); // channel
                writer.WriteEndElement(); // rss
                writer.WriteEndDocument();
            }
        }
示例#23
0
        public void GetProductPrice(Product product, out decimal price, out decimal priceWithDiscount)
        {
            price             = decimal.Zero;
            priceWithDiscount = decimal.Zero;

            if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
            {
                if (!product.CustomerEntersPrice)
                {
                    if (!product.CallForPrice)
                    {
                        decimal taxRate;
                        decimal oldPriceBase = _taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                        decimal finalPriceWithDiscountBase = _taxService.GetProductPrice(product, _priceCalculationService.GetFinalPrice(product, _workContext.CurrentCustomer, includeDiscounts: true), out taxRate);

                        price             = _currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, _workContext.WorkingCurrency);
                        priceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, _workContext.WorkingCurrency);

                        if (price == 0)
                        {
                            price             = priceWithDiscount;
                            priceWithDiscount = 0;
                        }
                    }
                }
            }
        }
        public static IEnumerable<ProductOverviewModel> PrepareProductOverviewModels(this Controller controller,
            IWorkContext workContext,
            IStoreContext storeContext,
            ICategoryService categoryService,
            IProductService productService,
            ISpecificationAttributeService specificationAttributeService,
            IPriceCalculationService priceCalculationService,
            IPriceFormatter priceFormatter,
            IPermissionService permissionService,
            ILocalizationService localizationService,
            ITaxService taxService,
            ICurrencyService currencyService,
            IPictureService pictureService,
            IWebHelper webHelper,
            ICacheManager cacheManager,
            CatalogSettings catalogSettings,
            MediaSettings mediaSettings,
            IEnumerable<Product> products,
            bool preparePriceModel = true, bool preparePictureModel = true,
            int? productThumbPictureSize = null, bool prepareSpecificationAttributes = false,
            bool forceRedirectionAfterAddingToCart = false)
        {
            if (products == null)
                throw new ArgumentNullException("products");

            var models = new List<ProductOverviewModel>();
            foreach (var product in products)
            {
                var model = new ProductOverviewModel
                {
                    Id = product.Id,
                    Name = product.GetLocalized(x => x.Name),
                    ShortDescription = product.GetLocalized(x => x.ShortDescription),
                    FullDescription = product.GetLocalized(x => x.FullDescription),
                    SeName = product.GetSeName(),
                };
                //price
                if (preparePriceModel)
                {
                    #region Prepare product price

                    var priceModel = new ProductOverviewModel.ProductPriceModel
                    {
                        ForceRedirectionAfterAddingToCart = forceRedirectionAfterAddingToCart
                    };

                    switch (product.ProductType)
                    {
                        case ProductType.GroupedProduct:
                            {
                                #region Grouped product

                                var associatedProducts = productService.GetAssociatedProducts(product.Id, storeContext.CurrentStore.Id);

                                switch (associatedProducts.Count)
                                {
                                    case 0:
                                        {
                                            //no associated products
                                            //priceModel.DisableBuyButton = true;
                                            //priceModel.DisableWishlistButton = true;
                                            //compare products
                                            priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                                            //priceModel.AvailableForPreOrder = false;
                                        }
                                        break;
                                    default:
                                        {
                                            //we have at least one associated product
                                            //priceModel.DisableBuyButton = true;
                                            //priceModel.DisableWishlistButton = true;
                                            //compare products
                                            priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;
                                            //priceModel.AvailableForPreOrder = false;

                                            if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                                            {
                                                //find a minimum possible price
                                                decimal? minPossiblePrice = null;
                                                Product minPriceProduct = null;
                                                foreach (var associatedProduct in associatedProducts)
                                                {
                                                    //calculate for the maximum quantity (in case if we have tier prices)
                                                    var tmpPrice = priceCalculationService.GetFinalPrice(associatedProduct,
                                                        workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);
                                                    if (!minPossiblePrice.HasValue || tmpPrice < minPossiblePrice.Value)
                                                    {
                                                        minPriceProduct = associatedProduct;
                                                        minPossiblePrice = tmpPrice;
                                                    }
                                                }
                                                if (minPriceProduct != null && !minPriceProduct.CustomerEntersPrice)
                                                {
                                                    if (minPriceProduct.CallForPrice)
                                                    {
                                                        priceModel.OldPrice = null;
                                                        priceModel.Price = localizationService.GetResource("Products.CallForPrice");
                                                    }
                                                    else if (minPossiblePrice.HasValue)
                                                    {
                                                        //calculate prices
                                                        decimal taxRate;
                                                        decimal finalPriceBase = taxService.GetProductPrice(minPriceProduct, minPossiblePrice.Value, out taxRate);
                                                        decimal finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                                        priceModel.OldPrice = null;
                                                        priceModel.Price = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));

                                                    }
                                                    else
                                                    {
                                                        //Actually it's not possible (we presume that minimalPrice always has a value)
                                                        //We never should get here
                                                        Debug.WriteLine("Cannot calculate minPrice for product #{0}", product.Id);
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                //hide prices
                                                priceModel.OldPrice = null;
                                                priceModel.Price = null;
                                            }
                                        }
                                        break;
                                }

                                #endregion
                            }
                            break;
                        case ProductType.SimpleProduct:
                        default:
                            {
                                #region Simple product

                                //add to cart button
                                priceModel.DisableBuyButton = product.DisableBuyButton ||
                                    !permissionService.Authorize(StandardPermissionProvider.EnableShoppingCart) ||
                                    !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);

                                //add to wishlist button
                                priceModel.DisableWishlistButton = product.DisableWishlistButton ||
                                    !permissionService.Authorize(StandardPermissionProvider.EnableWishlist) ||
                                    !permissionService.Authorize(StandardPermissionProvider.DisplayPrices);
                                //compare products
                                priceModel.DisableAddToCompareListButton = !catalogSettings.CompareProductsEnabled;

                                //rental
                                priceModel.IsRental = product.IsRental;

                                //pre-order
                                if (product.AvailableForPreOrder)
                                {
                                    priceModel.AvailableForPreOrder = !product.PreOrderAvailabilityStartDateTimeUtc.HasValue ||
                                        product.PreOrderAvailabilityStartDateTimeUtc.Value >= DateTime.UtcNow;
                                    priceModel.PreOrderAvailabilityStartDateTimeUtc = product.PreOrderAvailabilityStartDateTimeUtc;
                                }

                                //prices
                                if (permissionService.Authorize(StandardPermissionProvider.DisplayPrices))
                                {
                                    if (!product.CustomerEntersPrice)
                                    {
                                        if (product.CallForPrice)
                                        {
                                            //call for price
                                            priceModel.OldPrice = null;
                                            priceModel.Price = localizationService.GetResource("Products.CallForPrice");
                                        }
                                        else
                                        {
                                            //prices

                                            //calculate for the maximum quantity (in case if we have tier prices)
                                            decimal minPossiblePrice = priceCalculationService.GetFinalPrice(product,
                                                workContext.CurrentCustomer, decimal.Zero, true, int.MaxValue);

                                            decimal taxRate;
                                            decimal oldPriceBase = taxService.GetProductPrice(product, product.OldPrice, out taxRate);
                                            decimal finalPriceBase = taxService.GetProductPrice(product, minPossiblePrice, out taxRate);

                                            decimal oldPrice = currencyService.ConvertFromPrimaryStoreCurrency(oldPriceBase, workContext.WorkingCurrency);
                                            decimal finalPrice = currencyService.ConvertFromPrimaryStoreCurrency(finalPriceBase, workContext.WorkingCurrency);

                                            //do we have tier prices configured?
                                            var tierPrices = new List<TierPrice>();
                                            if (product.HasTierPrices)
                                            {
                                                tierPrices.AddRange(product.TierPrices
                                                    .OrderBy(tp => tp.Quantity)
                                                    .ToList()
                                                    .FilterByStore(storeContext.CurrentStore.Id)
                                                    .FilterForCustomer(workContext.CurrentCustomer)
                                                    .RemoveDuplicatedQuantities());
                                            }
                                            //When there is just one tier (with  qty 1),
                                            //there are no actual savings in the list.
                                            bool displayFromMessage = tierPrices.Count > 0 &&
                                                !(tierPrices.Count == 1 && tierPrices[0].Quantity <= 1);
                                            if (displayFromMessage)
                                            {
                                                priceModel.OldPrice = null;
                                                priceModel.Price = String.Format(localizationService.GetResource("Products.PriceRangeFrom"), priceFormatter.FormatPrice(finalPrice));
                                            }
                                            else
                                            {
                                                if (finalPriceBase != oldPriceBase && oldPriceBase != decimal.Zero)
                                                {
                                                    priceModel.OldPrice = priceFormatter.FormatPrice(oldPrice);
                                                    priceModel.Price = priceFormatter.FormatPrice(finalPrice);
                                                }
                                                else
                                                {
                                                    priceModel.OldPrice = null;
                                                    priceModel.Price = priceFormatter.FormatPrice(finalPrice);
                                                }
                                            }
                                            if (product.IsRental)
                                            {
                                                //rental product
                                                priceModel.OldPrice = priceFormatter.FormatRentalProductPeriod(product, priceModel.OldPrice);
                                                priceModel.Price = priceFormatter.FormatRentalProductPeriod(product, priceModel.Price);
                                            }

                                            //property for German market
                                            //we display tax/shipping info only with "shipping enabled" for this product
                                            //we also ensure this it's not free shipping
                                            priceModel.DisplayTaxShippingInfo = catalogSettings.DisplayTaxShippingInfoProductBoxes
                                                && product.IsShipEnabled &&
                                                !product.IsFreeShipping;
                                        }
                                    }
                                }
                                else
                                {
                                    //hide prices
                                    priceModel.OldPrice = null;
                                    priceModel.Price = null;
                                }

                                #endregion
                            }
                            break;
                    }

                    model.ProductPrice = priceModel;

                    #endregion
                }

                //picture
                if (preparePictureModel)
                {
                    #region Prepare product picture

                    //If a size has been set in the view, we use it in priority
                    int pictureSize = productThumbPictureSize.HasValue ? productThumbPictureSize.Value : mediaSettings.ProductThumbPictureSize;
                    //prepare picture model
                    var defaultProductPictureCacheKey = string.Format(ModelCacheEventConsumer.PRODUCT_DEFAULTPICTURE_MODEL_KEY, product.Id, pictureSize, true, workContext.WorkingLanguage.Id, webHelper.IsCurrentConnectionSecured(), storeContext.CurrentStore.Id);
                    model.DefaultPictureModel = cacheManager.Get(defaultProductPictureCacheKey, () =>
                    {
                        var picture = pictureService.GetPicturesByProductId(product.Id, 1).FirstOrDefault();
                        var pictureModel = new PictureModel
                        {
                            ImageUrl = pictureService.GetPictureUrl(picture, pictureSize),
                            FullSizeImageUrl = pictureService.GetPictureUrl(picture)
                        };
                        //"title" attribute
                        pictureModel.Title = (picture != null && !string.IsNullOrEmpty(picture.TitleAttribute)) ?
                            picture.TitleAttribute :
                            string.Format(localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), model.Name);
                        //"alt" attribute
                        pictureModel.AlternateText = (picture != null && !string.IsNullOrEmpty(picture.AltAttribute)) ?
                            picture.AltAttribute :
                            string.Format(localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), model.Name);

                        return pictureModel;
                    });

                    #endregion
                }

                //specs
                if (prepareSpecificationAttributes)
                {
                    model.SpecificationAttributeModels = PrepareProductSpecificationModel(controller, workContext,
                         specificationAttributeService, cacheManager, product);
                }

                //reviews
                model.ReviewOverviewModel = new ProductReviewOverviewModel
                {
                    ProductId = product.Id,
                    RatingSum = product.ApprovedRatingSum,
                    TotalReviews = product.ApprovedTotalReviews,
                    AllowCustomerReviews = product.AllowCustomerReviews
                };

                models.Add(model);
            }
            return models;
        }
        /// <summary>
        /// Gets the base price info
        /// </summary>
        /// <param name="product">Product</param>
        /// <param name="localizationService">Localization service</param>
        /// <param name="priceFormatter">Price formatter</param>
        /// <param name="currencyService">Currency service</param>
        /// <param name="taxService">Tax service</param>
        /// <param name="priceCalculationService">Price calculation service</param>
        /// <param name="currency">Target currency</param>
        /// <param name="priceAdjustment">Price adjustment</param>
        /// <param name="languageInsensitive">Whether the result string should be language insensitive</param>
        /// <returns>The base price info</returns>
        public static string GetBasePriceInfo(this Product product,
			ILocalizationService localizationService,
			IPriceFormatter priceFormatter,
            ICurrencyService currencyService,
			ITaxService taxService,
			IPriceCalculationService priceCalculationService,
            Currency currency,
			decimal priceAdjustment = decimal.Zero,
			bool languageInsensitive = false)
        {
            Guard.ArgumentNotNull(() => product);
            Guard.ArgumentNotNull(() => currencyService);
            Guard.ArgumentNotNull(() => taxService);
            Guard.ArgumentNotNull(() => priceCalculationService);
            Guard.ArgumentNotNull(() => currency);

            if (product.BasePriceHasValue && product.BasePriceAmount != Decimal.Zero)
            {
                var workContext = EngineContext.Current.Resolve<IWorkContext>();

                var taxrate = decimal.Zero;
                var currentPrice = priceCalculationService.GetFinalPrice(product, workContext.CurrentCustomer, true);
                var price = taxService.GetProductPrice(product, decimal.Add(currentPrice, priceAdjustment), out taxrate);

                price = currencyService.ConvertFromPrimaryStoreCurrency(price, currency);

                return product.GetBasePriceInfo(price, localizationService, priceFormatter, currency, languageInsensitive);
            }

            return "";
        }