public PaymentDetailsItemType CreatePaymentItem(ShoppingCartItem item) { var product = _productService.GetProductById(item.ProductId); if (product is null) { throw new NopException("Product is not found"); } var productPrice = _taxService.GetProductPrice(product, _shoppingCartService.GetUnitPrice(item), false, _workContext.CurrentCustomer, out _); var currencyCodeType = _payPalCurrencyCodeParser.GetCurrencyCodeType(_workContext.WorkingCurrency); var paymentDetailsItemType = new PaymentDetailsItemType { Name = product.Name, //Description = _productAttributeFormatter.FormatAttributes(item.ProductVariant, item.AttributesXml), Amount = productPrice.GetBasicAmountType(currencyCodeType), ItemCategory = product.IsDownload ? ItemCategoryType.Digital : ItemCategoryType.Physical, Quantity = item.Quantity.ToString() }; return(paymentDetailsItemType); }
private async Task <(string Price, string PriceWithDiscount)> PreparePrice(Product product, GetSearchAutoComplete request) { string price, priceWithDiscount; double finalPriceWithoutDiscount = (await(_taxService.GetProductPrice(product, (await _pricingService.GetFinalPrice(product, request.Customer, request.Currency, includeDiscounts: false)).finalPrice))).productprice; var appliedPrice = (await _pricingService.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); }
/// <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(""); }
/// <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); }
public void Can_get_productPrice_priceIncludesTax_includingTax_taxable() { var customer = new Customer(); var product = new Product(); _taxService.GetProductPrice(product, 0, 1000M, true, customer, true, out decimal taxRate).ShouldEqual(1000); _taxService.GetProductPrice(product, 0, 1000M, true, customer, false, out taxRate).ShouldEqual(1100); _taxService.GetProductPrice(product, 0, 1000M, false, customer, true, out taxRate).ShouldEqual(909.0909090909090909090909091M); _taxService.GetProductPrice(product, 0, 1000M, false, customer, false, out taxRate).ShouldEqual(1000); }
public ActionResult GetCartDetails(int customerId) { var gridModel = new GridModel <ShoppingCartItemModel>(); if (Services.Permissions.Authorize(StandardPermissionProvider.ManageOrders)) { decimal taxRate; var customer = _customerService.GetCustomerById(customerId); var cart = customer.GetCartItems(ShoppingCartType.ShoppingCart); gridModel.Data = cart.Select(sci => { var store = Services.StoreService.GetStoreById(sci.Item.StoreId); var sciModel = new ShoppingCartItemModel { Id = sci.Item.Id, Store = store != null ? store.Name : "".NaIfEmpty(), ProductId = sci.Item.ProductId, Quantity = sci.Item.Quantity, ProductName = sci.Item.Product.Name, ProductTypeName = sci.Item.Product.GetProductTypeLabel(Services.Localization), ProductTypeLabelHint = sci.Item.Product.ProductTypeLabelHint, UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Item.Product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate)), Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Item.Product, _priceCalculationService.GetSubTotal(sci, true), out taxRate)), UpdatedOn = _dateTimeHelper.ConvertToUserTime(sci.Item.UpdatedOnUtc, DateTimeKind.Utc) }; return(sciModel); }); gridModel.Total = cart.Count; } else { gridModel.Data = Enumerable.Empty <ShoppingCartItemModel>(); NotifyAccessDenied(); } return(new JsonResult { Data = gridModel }); }
/// <summary> /// Prepare paged shopping cart item list model /// </summary> /// <param name="searchModel">Shopping cart item search model</param> /// <param name="customer">Customer</param> /// <returns>Shopping cart item list model</returns> public virtual ShoppingCartItemListModel PrepareShoppingCartItemListModel(ShoppingCartItemSearchModel searchModel, Customer customer) { if (searchModel == null) { throw new ArgumentNullException(nameof(searchModel)); } if (customer == null) { throw new ArgumentNullException(nameof(customer)); } //get shopping cart items var items = customer.ShoppingCartItems.Where(item => item.ShoppingCartType == searchModel.ShoppingCartType).ToList(); //prepare list model var model = new ShoppingCartItemListModel { Data = items.PaginationByRequestModel(searchModel).Select(item => { //fill in model values from the entity var itemModel = item.ToModel <ShoppingCartItemModel>(); //convert dates to the user time itemModel.UpdatedOn = _dateTimeHelper.ConvertToUserTime(item.UpdatedOnUtc, DateTimeKind.Utc); //fill in additional values (not existing in the entity) itemModel.Store = _storeService.GetStoreById(item.StoreId)?.Name ?? "Deleted"; itemModel.AttributeInfo = _productAttributeFormatter.FormatAttributes(item.Product, item.AttributesXml, item.Customer); var unitPrice = _priceCalculationService.GetUnitPrice(item); itemModel.UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(item.Product, unitPrice, out var _)); var subTotal = _priceCalculationService.GetSubTotal(item); itemModel.Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(item.Product, subTotal, out _)); return(itemModel); }), Total = items.Count }; return(model); } #endregion }
public void CanGetProductPricePriceIncludesTaxIncludingTaxTaxable() { var customer = new Customer(); var product = new Product(); _taxService.GetProductPrice(product, 0, 1000M, true, customer, true, out _).Should().Be(1000); _taxService.GetProductPrice(product, 0, 1000M, true, customer, false, out _).Should().Be(1100); _taxService.GetProductPrice(product, 0, 1000M, false, customer, true, out _).Should() .Be(909.0909090909090909090909091M); _taxService.GetProductPrice(product, 0, 1000M, false, customer, false, out _).Should().Be(1000); }
private async Task <(string Price, string PriceWithDiscount)> PreparePrice(Product product, GetSearchAutoComplete request) { string price, priceWithDiscount; decimal finalPriceWithoutDiscountBase = (await(_taxService.GetProductPrice(product, (await _priceCalculationService.GetFinalPrice(product, request.Customer, includeDiscounts: false)).finalPrice))).productprice; var appliedPrice = (await _priceCalculationService.GetFinalPrice(product, request.Customer, includeDiscounts: true)); var finalPriceWithDiscountBase = (await _taxService.GetProductPrice(product, appliedPrice.finalPrice)).productprice; var finalPriceWithoutDiscount = await _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithoutDiscountBase, request.Currency); var finalPriceWithDiscount = await _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, request.Currency); price = _priceFormatter.FormatPrice(finalPriceWithoutDiscount); priceWithDiscount = _priceFormatter.FormatPrice(finalPriceWithDiscount); return(price, priceWithDiscount); }
/// <summary> /// Prepare paged shopping cart item list model /// </summary> /// <param name="searchModel">Shopping cart item search model</param> /// <param name="customer">Customer</param> /// <returns>Shopping cart item list model</returns> public virtual ShoppingCartItemListModel PrepareShoppingCartItemListModel(ShoppingCartItemSearchModel searchModel, Customer customer) { if (searchModel == null) { throw new ArgumentNullException(nameof(searchModel)); } if (customer == null) { throw new ArgumentNullException(nameof(customer)); } //get shopping cart items var items = _shoppingCartService.GetShoppingCart(customer, searchModel.ShoppingCartType, searchModel.StoreId, searchModel.ProductId, searchModel.StartDate, searchModel.EndDate).ToPagedList(searchModel); //prepare list model var model = new ShoppingCartItemListModel().PrepareToGrid(searchModel, items, () => { return(items.Select(item => { //fill in model values from the entity var itemModel = item.ToModel <ShoppingCartItemModel>(); //convert dates to the user time itemModel.UpdatedOn = _dateTimeHelper.ConvertToUserTime(item.UpdatedOnUtc, DateTimeKind.Utc); //fill in additional values (not existing in the entity) itemModel.Store = _storeService.GetStoreById(item.StoreId)?.Name ?? "Deleted"; itemModel.AttributeInfo = _productAttributeFormatter.FormatAttributes(item.Product, item.AttributesXml, item.Customer); var unitPrice = _priceCalculationService.GetUnitPrice(item); itemModel.UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(item.Product, unitPrice, out var _)); var subTotal = _priceCalculationService.GetSubTotal(item); itemModel.Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(item.Product, subTotal, out _)); //set product name since it does not survive mapping itemModel.ProductName = item?.Product?.Name; return itemModel; })); });
public HttpResponseMessage GetCartDetails(HttpRequestMessage request, int customerId) { return(CreateHttpResponse(request, () => { HttpResponseMessage response = request.CreateErrorResponse(HttpStatusCode.NotFound, "No items found"); if (true) { var customer = _customerService.GetCustomerById(customerId); var cart = customer.ShoppingCartItems.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList(); var gridModel = new DataSourceResult { Data = cart.Select(sci => { decimal taxRate; var store = _storeService.GetStoreById(sci.StoreId); var sciModel = new ShoppingCartItemVM { Id = sci.Id, Store = store != null ? store.Name : "Unknown", ProductId = sci.ProductId, Quantity = sci.Quantity, ProductName = sci.Product.Name, AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.Product, sci.AttributesXml, sci.Customer), UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci), out taxRate)), Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci), out taxRate)), UpdatedOn = _dateTimeHelper.ConvertToUserTime(sci.UpdatedOnUtc, DateTimeKind.Utc) }; return sciModel; }), Total = cart.Count }; response = request.CreateResponse <DataSourceResult>(HttpStatusCode.OK, gridModel); } else { response = request.CreateResponse(HttpStatusCode.Unauthorized, "Unauthorized user"); } return response; })); }
public ActionResult GetCartDetails(int customerId) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrentCarts)) { return(AccessDeniedView()); } var customer = _customerService.GetCustomerById(customerId); var cart = customer.ShoppingCartItems.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList(); var gridModel = new DataSourceResult { Data = cart.Select(sci => { decimal taxRate; var store = _storeService.GetStoreById(sci.StoreId); var sciModel = new ShoppingCartItemModel() { Id = sci.Id, Store = store != null ? store.Name : "Unknown", ProductId = sci.ProductId, Quantity = sci.Quantity, ProductName = sci.Product.Name, UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate)), Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, true), out taxRate)), UpdatedOn = _dateTimeHelper.ConvertToUserTime(sci.UpdatedOnUtc, DateTimeKind.Utc) }; return(sciModel); }), Total = cart.Count }; return(Json(gridModel)); }
/// <summary> /// Get transaction line items /// </summary> /// <param name="customer">Customer</param> /// <param name="storeId">Store identifier</param> /// <returns>List of transaction items</returns> private List <BasketItem> GetItems(Core.Domain.Customers.Customer customer, int storeId) { var items = new List <BasketItem>(); //get current shopping cart var shoppingCart = _shoppingCartService.GetShoppingCart(customer, ShoppingCartType.ShoppingCart, storeId); //define function to create item BasketItem createItem(decimal price, string productId, string productName, string categoryName, BasketItemType itemType = BasketItemType.PHYSICAL) { return(new BasketItem { Id = productId, Name = productName, Category1 = categoryName, ItemType = itemType.ToString(), Price = Convert.ToDecimal(price, CultureInfo.InvariantCulture).ToString("f8", CultureInfo.InvariantCulture), }); } items.AddRange(shoppingCart.Select(sci => { var product = _productService.GetProductById(sci.ProductId); var shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(product, _shoppingCartService.GetUnitPrice(sci), out var _); var shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency); return(createItem(shoppingCartUnitPriceWithDiscount * sci.Quantity, product.Id.ToString(), product.Name, _categoryService.GetProductCategoriesByProductId(sci.ProductId).Aggregate(",", (all, pc) => { var res = _categoryService.GetCategoryById(pc.CategoryId).Name; res = all == "," ? res : all + ", " + res; return res; }))); })); //shipping without tax var shoppingCartShipping = _orderTotalCalculationService.GetShoppingCartShippingTotal(shoppingCart, false); if (shoppingCartShipping.HasValue && shoppingCartShipping.Value != 0) { items.Add(createItem(shoppingCartShipping ?? 0, Guid.NewGuid().ToString(), "Shipping", "Shipping", BasketItemType.VIRTUAL)); } return(items); }
public ActionResult GetCartDetails(int customerId) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageOrders)) { return(AccessDeniedView()); } var customer = _customerService.GetCustomerById(customerId); var cart = customer.GetCartItems(ShoppingCartType.ShoppingCart); var gridModel = new GridModel <ShoppingCartItemModel>() { Data = cart.Select(sci => { decimal taxRate; var store = _storeService.GetStoreById(sci.Item.StoreId); var sciModel = new ShoppingCartItemModel() { Id = sci.Item.Id, Store = store != null ? store.Name : "Unknown", ProductId = sci.Item.ProductId, Quantity = sci.Item.Quantity, ProductName = sci.Item.Product.Name, ProductTypeName = sci.Item.Product.GetProductTypeLabel(_localizationService), ProductTypeLabelHint = sci.Item.Product.ProductTypeLabelHint, UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Item.Product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate)), Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.Item.Product, _priceCalculationService.GetSubTotal(sci, true), out taxRate)), UpdatedOn = _dateTimeHelper.ConvertToUserTime(sci.Item.UpdatedOnUtc, DateTimeKind.Utc) }; return(sciModel); }), Total = cart.Count }; return(new JsonResult { Data = gridModel }); }
public ActionResult GetCartDetails(int customerId) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageOrders)) { return(AccessDeniedView()); } var customer = _customerService.GetCustomerById(customerId); var cart = customer.ShoppingCartItems.Where(x => x.ShoppingCartType == ShoppingCartType.ShoppingCart).ToList(); var gridModel = new GridModel <ShoppingCartItemModel>() { Data = cart.Select(sci => { decimal taxRate; var sciModel = new ShoppingCartItemModel() { Id = sci.Id, Store = sci.Store != null ? sci.Store.Name : "Unknown", ProductVariantId = sci.ProductVariantId, Quantity = sci.Quantity, FullProductName = !String.IsNullOrEmpty(sci.ProductVariant.Name) ? string.Format("{0} ({1})", sci.ProductVariant.Product.Name, sci.ProductVariant.Name) : sci.ProductVariant.Product.Name, UnitPrice = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetUnitPrice(sci, true), out taxRate)), Total = _priceFormatter.FormatPrice(_taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetSubTotal(sci, true), out taxRate)), UpdatedOn = _dateTimeHelper.ConvertToUserTime(sci.UpdatedOnUtc, DateTimeKind.Utc) }; return(sciModel); }), Total = cart.Count }; return(new JsonResult { Data = gridModel }); }
private bool CheckCurrentSubTotalRequirement(CheckDiscountRequirementRequest request, bool includingDiscount = true) { var cartItems = request.Customer.GetCartItems(ShoppingCartType.ShoppingCart, request.Store.Id); decimal spentAmount = decimal.Zero; decimal taxRate = decimal.Zero; foreach (var sci in cartItems) { spentAmount += sci.Item.Quantity * _taxService.GetProductPrice(sci.Item.Product, _priceCalculationService.GetUnitPrice(sci, includingDiscount), out taxRate); } return(spentAmount >= request.DiscountRequirement.SpentAmount); }
private OrderItem PrepareDefaultOrderItemFromProduct(Order order, Product product) { var presetQty = 1; var presetPrice = _priceCalculationService.GetFinalPrice(product, order.Customer, decimal.Zero, true, presetQty); decimal taxRate; decimal presetPriceInclTax = _taxService.GetProductPrice(product, presetPrice, true, order.Customer, out taxRate); decimal presetPriceExclTax = _taxService.GetProductPrice(product, presetPrice, false, order.Customer, out taxRate); OrderItem 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); }
public void Can_get_productPrice_priceIncludesTax_includingTax_taxable() { var customer = new Customer(); var product = new Product(); var serviceProvider = new FakeServiceProvider(_genericAttributeService.Object, _taxService, _taxSettings); var nopEngine = new FakeNopEngine(serviceProvider); EngineContext.Replace(nopEngine); _taxService.GetProductPrice(product, 0, 1000M, true, customer, true, out _).Should().Be(1000); _taxService.GetProductPrice(product, 0, 1000M, true, customer, false, out _).Should().Be(1100); _taxService.GetProductPrice(product, 0, 1000M, false, customer, true, out _).Should() .Be(909.0909090909090909090909091M); _taxService.GetProductPrice(product, 0, 1000M, false, customer, false, out _).Should().Be(1000); EngineContext.Replace(null); }
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)); }
public PaymentDetailsItemType CreatePaymentItem(ShoppingCartItem item) { decimal taxRate; var productPrice = _taxService.GetProductPrice(item.Product, _priceCalculationService.GetUnitPrice(item, true), false, _workContext.CurrentCustomer, out taxRate); var currencyCodeType = _payPalCurrencyCodeParser.GetCurrencyCodeType(_workContext.WorkingCurrency); var paymentDetailsItemType = new PaymentDetailsItemType { Name = item.Product.Name, //Description = _productAttributeFormatter.FormatAttributes(item.ProductVariant, item.AttributesXml), Amount = productPrice.GetBasicAmountType(currencyCodeType), ItemCategory = item.Product.IsDownload ? ItemCategoryType.Digital : ItemCategoryType.Physical, Quantity = item.Quantity.ToString() }; return(paymentDetailsItemType); }
private bool CheckCurrentSubTotalRequirement(CheckDiscountRequirementRequest request) { var spentAmount = decimal.Zero; try { var taxRate = decimal.Zero; var cartItems = request.Customer.GetCartItems(ShoppingCartType.ShoppingCart, request.Store.Id); foreach (var cartItem in cartItems) { var product = cartItem.Item.Product; Dictionary <string, object> mergedValuesClone = null; // we must reapply merged values because CheckCurrentSubTotalRequirement uses price calculation and is called by it itself. // this can cause wrong discount calculation if the cart contains a product several times. if (product.MergedDataValues != null) { mergedValuesClone = new Dictionary <string, object>(product.MergedDataValues); } // includeDiscounts == true produces a stack overflow! spentAmount += cartItem.Item.Quantity * _taxService.GetProductPrice(product, _priceCalculationService.GetUnitPrice(cartItem, false), out taxRate); if (mergedValuesClone != null) { product.MergedDataValues = new Dictionary <string, object>(mergedValuesClone); } } } catch (Exception exception) { _logger.Error(exception); return(false); } return(spentAmount >= request.DiscountRequirement.SpentAmount); }
/// <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(""); }
/// <summary> /// Create items from shopping cart /// </summary> /// <param name="shoppingCart">Shopping cart</param> /// <returns>Collection of PayPal items</returns> protected IEnumerable <Item> CreateItems(IEnumerable <ShoppingCartItem> shoppingCart) { return(shoppingCart.Select(shoppingCartItem => { if (shoppingCartItem.Product == null) { return null; } var item = new Item { //name name = shoppingCartItem.Product.Name }; //SKU if (!string.IsNullOrEmpty(shoppingCartItem.AttributesXml)) { var combination = _productAttributeParser.FindProductAttributeCombination(shoppingCartItem.Product, shoppingCartItem.AttributesXml); item.sku = combination != null && !string.IsNullOrEmpty(combination.Sku) ? combination.Sku : shoppingCartItem.Product.Sku; } else { item.sku = shoppingCartItem.Product.Sku; } //item price var unitPrice = _priceCalculationService.GetUnitPrice(shoppingCartItem); var price = _taxService.GetProductPrice(shoppingCartItem.Product, unitPrice, false, shoppingCartItem.Customer, out decimal _); item.price = price.ToString("N", new CultureInfo("en-US")); //quantity item.quantity = shoppingCartItem.Quantity.ToString(); return item; })); }
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; }
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); }
private async Task <StringBuilder> PrepareFormattedAttribute(Product product, string attributesXml, string langId, string serapator, bool htmlEncode, bool renderPrices, bool allowHyperlinks, bool showInAdmin) { var result = new StringBuilder(); var attributes = _productAttributeParser.ParseProductAttributeMappings(product, attributesXml); for (int i = 0; i < attributes.Count; i++) { var productAttribute = await _productAttributeService.GetProductAttributeById(attributes[i].ProductAttributeId); var attribute = attributes[i]; var valuesStr = _productAttributeParser.ParseValues(attributesXml, attribute.Id); for (int j = 0; j < valuesStr.Count; j++) { string valueStr = valuesStr[j]; string formattedAttribute = string.Empty; if (!attribute.ShouldHaveValues()) { //no values if (attribute.AttributeControlType == AttributeControlType.MultilineTextbox) { //multiline textbox var attributeName = productAttribute.GetLocalized(a => a.Name, langId); //encode (if required) if (htmlEncode) { attributeName = WebUtility.HtmlEncode(attributeName); } formattedAttribute = string.Format("{0}: {1}", attributeName, HtmlHelper.FormatText(valueStr)); //we never encode multiline textbox input } else if (attribute.AttributeControlType == AttributeControlType.FileUpload) { //file upload Guid downloadGuid; Guid.TryParse(valueStr, out downloadGuid); var download = await _downloadService.GetDownloadByGuid(downloadGuid); if (download != null) { //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) string attributeText = ""; var fileName = string.Format("{0}{1}", download.Filename ?? download.DownloadGuid.ToString(), download.Extension); //encode (if required) if (htmlEncode) { fileName = WebUtility.HtmlEncode(fileName); } if (allowHyperlinks) { //hyperlinks are allowed var downloadLink = string.Format("{0}download/getfileupload/?downloadId={1}", _webHelper.GetStoreLocation(false), download.DownloadGuid); attributeText = string.Format("<a href=\"{0}\" class=\"fileuploadattribute\">{1}</a>", downloadLink, fileName); } else { //hyperlinks aren't allowed attributeText = fileName; } var attributeName = productAttribute.GetLocalized(a => a.Name, langId); //encode (if required) if (htmlEncode) { attributeName = WebUtility.HtmlEncode(attributeName); } formattedAttribute = string.Format("{0}: {1}", attributeName, attributeText); } } else { //other attributes (textbox, datepicker) formattedAttribute = string.Format("{0}: {1}", productAttribute.GetLocalized(a => a.Name, langId), valueStr); //encode (if required) if (htmlEncode) { formattedAttribute = WebUtility.HtmlEncode(formattedAttribute); } } } else { //attributes with values if (product.ProductAttributeMappings.Where(x => x.Id == attributes[i].Id).FirstOrDefault() != null) { var attributeValue = product.ProductAttributeMappings.Where(x => x.Id == attributes[i].Id).FirstOrDefault().ProductAttributeValues.Where(x => x.Id == valueStr).FirstOrDefault(); if (attributeValue != null) { formattedAttribute = string.Format("{0}: {1}", productAttribute.GetLocalized(a => a.Name, langId), attributeValue.GetLocalized(a => a.Name, langId)); if (renderPrices) { decimal attributeValuePriceAdjustment = await _priceCalculationService.GetProductAttributeValuePriceAdjustment(attributeValue); var prices = await _taxService.GetProductPrice(product, attributeValuePriceAdjustment, _workContext.CurrentCustomer); decimal priceAdjustmentBase = prices.productprice; decimal taxRate = prices.taxRate; decimal priceAdjustment = await _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > 0) { string priceAdjustmentStr = _priceFormatter.FormatPrice(priceAdjustment, false, false); formattedAttribute += string.Format(" [+{0}]", priceAdjustmentStr); } else if (priceAdjustmentBase < decimal.Zero) { string priceAdjustmentStr = _priceFormatter.FormatPrice(-priceAdjustment, false, false); formattedAttribute += string.Format(" [-{0}]", priceAdjustmentStr); } } //display quantity if (_shoppingCartSettings.RenderAssociatedAttributeValueQuantity && attributeValue.AttributeValueType == AttributeValueType.AssociatedToProduct) { //render only when more than 1 if (attributeValue.Quantity > 1) { //TODO localize resource formattedAttribute += string.Format(" - qty {0}", attributeValue.Quantity); } } } else { if (showInAdmin) { formattedAttribute += string.Format("{0}: {1}", productAttribute.GetLocalized(a => a.Name, langId), ""); } } //encode (if required) if (htmlEncode) { formattedAttribute = WebUtility.HtmlEncode(formattedAttribute); } } } if (!String.IsNullOrEmpty(formattedAttribute)) { if (i != 0 || j != 0) { result.Append(serapator); } result.Append(formattedAttribute); } } } return(result); }
/// <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(); } }
public async Task <ProductDetailsAttributeChangeModel> Handle(GetProductDetailsAttributeChange request, CancellationToken cancellationToken) { var model = new ProductDetailsAttributeChangeModel(); string attributeXml = await _mediator.Send(new GetParseProductAttributes() { Product = request.Product, Form = request.Form }); string warehouseId = _shoppingCartSettings.AllowToSelectWarehouse ? request.Form["WarehouseId"].ToString() : request.Product.UseMultipleWarehouses ? request.Store.DefaultWarehouseId : (string.IsNullOrEmpty(request.Store.DefaultWarehouseId) ? request.Product.WarehouseId : request.Store.DefaultWarehouseId); //rental attributes DateTime?rentalStartDate = null; DateTime?rentalEndDate = null; if (request.Product.ProductType == ProductType.Reservation) { request.Product.ParseReservationDates(request.Form, out rentalStartDate, out rentalEndDate); } model.Sku = request.Product.FormatSku(attributeXml, _productAttributeParser); model.Mpn = request.Product.FormatMpn(attributeXml, _productAttributeParser); model.Gtin = request.Product.FormatGtin(attributeXml, _productAttributeParser); if (await _permissionService.Authorize(StandardPermissionProvider.DisplayPrices) && !request.Product.CustomerEntersPrice && request.Product.ProductType != ProductType.Auction) { //we do not calculate price of "customer enters price" option is enabled var unitprice = await _priceCalculationService.GetUnitPrice(request.Product, request.Customer, ShoppingCartType.ShoppingCart, 1, attributeXml, 0, rentalStartDate, rentalEndDate, true); decimal discountAmount = unitprice.discountAmount; List <AppliedDiscount> scDiscounts = unitprice.appliedDiscounts; decimal finalPrice = unitprice.unitprice; var productprice = await _taxService.GetProductPrice(request.Product, finalPrice); decimal finalPriceWithDiscountBase = productprice.productprice; decimal taxRate = productprice.taxRate; decimal finalPriceWithDiscount = await _currencyService.ConvertFromPrimaryStoreCurrency(finalPriceWithDiscountBase, request.Currency); model.Price = _priceFormatter.FormatPrice(finalPriceWithDiscount); } //stock model.StockAvailability = request.Product.FormatStockMessage(warehouseId, attributeXml, _localizationService, _productAttributeParser); //back in stock subscription if ((request.Product.ManageInventoryMethod == ManageInventoryMethod.ManageStockByAttributes || request.Product.ManageInventoryMethod == ManageInventoryMethod.ManageStock) && request.Product.BackorderMode == BackorderMode.NoBackorders && request.Product.AllowBackInStockSubscriptions) { var combination = _productAttributeParser.FindProductAttributeCombination(request.Product, attributeXml); if (combination != null) { if (request.Product.GetTotalStockQuantityForCombination(combination, warehouseId: request.Store.DefaultWarehouseId) <= 0) { model.DisplayBackInStockSubscription = true; } } if (request.Product.ManageInventoryMethod == ManageInventoryMethod.ManageStock) { model.DisplayBackInStockSubscription = request.Product.AllowBackInStockSubscriptions; attributeXml = ""; } var subscription = await _backInStockSubscriptionService .FindSubscription(request.Customer.Id, request.Product.Id, attributeXml, request.Store.Id, warehouseId); if (subscription != null) { model.ButtonTextBackInStockSubscription = _localizationService.GetResource("BackInStockSubscriptions.DeleteNotifyWhenAvailable"); } else { model.ButtonTextBackInStockSubscription = _localizationService.GetResource("BackInStockSubscriptions.NotifyMeWhenAvailable"); } } //conditional attributes if (request.ValidateAttributeConditions) { var attributes = request.Product.ProductAttributeMappings; foreach (var attribute in attributes) { var conditionMet = _productAttributeParser.IsConditionMet(request.Product, attribute, attributeXml); if (conditionMet.HasValue) { if (conditionMet.Value) { model.EnabledAttributeMappingIds.Add(attribute.Id); } else { model.DisabledAttributeMappingids.Add(attribute.Id); } } } } //picture. used when we want to override a default product picture when some attribute is selected if (request.LoadPicture) { //first, try to get product attribute combination picture var pictureId = request.Product.ProductAttributeCombinations.Where(x => x.AttributesXml == attributeXml).FirstOrDefault()?.PictureId ?? ""; //then, let's see whether we have attribute values with pictures if (string.IsNullOrEmpty(pictureId)) { pictureId = _productAttributeParser.ParseProductAttributeValues(request.Product, attributeXml) .FirstOrDefault(attributeValue => !string.IsNullOrEmpty(attributeValue.PictureId))?.PictureId ?? ""; } if (!string.IsNullOrEmpty(pictureId)) { var pictureModel = new PictureModel { Id = pictureId, FullSizeImageUrl = await _pictureService.GetPictureUrl(pictureId), ImageUrl = await _pictureService.GetPictureUrl(pictureId, _mediaSettings.ProductDetailsPictureSize) }; model.PictureFullSizeUrl = pictureModel.FullSizeImageUrl; model.PictureDefaultSizeUrl = pictureModel.ImageUrl; } } return(model); }
public PayPalResponse CreatePayment( PayPalApiSettingsBase settings, PayPalSessionData session, List <OrganizedShoppingCartItem> cart, string providerSystemName, string returnUrl, string cancelUrl) { var store = _services.StoreContext.CurrentStore; var customer = _services.WorkContext.CurrentCustomer; var language = _services.WorkContext.WorkingLanguage; var currencyCode = store.PrimaryStoreCurrency.CurrencyCode; var dateOfBirth = customer.GetAttribute <DateTime?>(SystemCustomerAttributeNames.DateOfBirth); Discount orderAppliedDiscount; List <AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints = 0; decimal redeemedRewardPointsAmount; decimal orderDiscountInclTax; decimal totalOrderItems = decimal.Zero; var includingTax = (_services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id) == TaxDisplayType.IncludingTax); var shipping = (_orderTotalCalculationService.GetShoppingCartShippingTotal(cart) ?? decimal.Zero); var paymentFee = _paymentService.GetAdditionalHandlingFee(cart, providerSystemName); var total = (_orderTotalCalculationService.GetShoppingCartTotal(cart, out orderDiscountInclTax, out orderAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount) ?? decimal.Zero); var data = new Dictionary <string, object>(); var redirectUrls = new Dictionary <string, object>(); var payer = new Dictionary <string, object>(); var payerInfo = new Dictionary <string, object>(); var transaction = new Dictionary <string, object>(); var amount = new Dictionary <string, object>(); var amountDetails = new Dictionary <string, object>(); var items = new List <Dictionary <string, object> >(); var itemList = new Dictionary <string, object>(); // "PayPal PLUS only supports transaction type “Sale” (instant settlement)" if (providerSystemName == PayPalPlusProvider.SystemName) { data.Add("intent", "sale"); } else { data.Add("intent", settings.TransactMode == TransactMode.AuthorizeAndCapture ? "sale" : "authorize"); } if (settings.ExperienceProfileId.HasValue()) { data.Add("experience_profile_id", settings.ExperienceProfileId); } // redirect urls if (returnUrl.HasValue()) { redirectUrls.Add("return_url", returnUrl); } if (cancelUrl.HasValue()) { redirectUrls.Add("cancel_url", cancelUrl); } if (redirectUrls.Any()) { data.Add("redirect_urls", redirectUrls); } // payer, payer_info if (dateOfBirth.HasValue) { payerInfo.Add("birth_date", dateOfBirth.Value.ToString("yyyy-MM-dd")); } if (customer.BillingAddress != null) { payerInfo.Add("billing_address", CreateAddress(customer.BillingAddress, false)); } payer.Add("payment_method", "paypal"); payer.Add("payer_info", payerInfo); data.Add("payer", payer); // line items foreach (var item in cart) { decimal unitPriceTaxRate = decimal.Zero; decimal unitPrice = _priceCalculationService.GetUnitPrice(item, true); decimal productPrice = _taxService.GetProductPrice(item.Item.Product, unitPrice, includingTax, customer, out unitPriceTaxRate); var line = new Dictionary <string, object>(); line.Add("quantity", item.Item.Quantity); line.Add("name", item.Item.Product.GetLocalized(x => x.Name, language.Id, true, false).Truncate(127)); line.Add("price", productPrice.FormatInvariant()); line.Add("currency", currencyCode); line.Add("sku", item.Item.Product.Sku.Truncate(50)); items.Add(line); totalOrderItems += (productPrice * item.Item.Quantity); } var itemsPlusMisc = (totalOrderItems + shipping + paymentFee); if (total != itemsPlusMisc) { var line = new Dictionary <string, object>(); line.Add("quantity", "1"); line.Add("name", T("Plugins.SmartStore.PayPal.Other").Text.Truncate(127)); line.Add("price", (total - itemsPlusMisc).FormatInvariant()); line.Add("currency", currencyCode); items.Add(line); totalOrderItems += (total - itemsPlusMisc); } itemList.Add("items", items); if (customer.ShippingAddress != null) { itemList.Add("shipping_address", CreateAddress(customer.ShippingAddress, true)); } // transactions amountDetails.Add("shipping", shipping.FormatInvariant()); amountDetails.Add("subtotal", totalOrderItems.FormatInvariant()); if (!includingTax) { // "To avoid rounding errors we recommend not submitting tax amounts on line item basis. // Calculated tax amounts for the entire shopping basket may be submitted in the amount objects. // In this case the item amounts will be treated as amounts excluding tax. // In a B2C scenario, where taxes are included, no taxes should be submitted to PayPal." SortedDictionary <decimal, decimal> taxRates = null; var taxTotal = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates); amountDetails.Add("tax", taxTotal.FormatInvariant()); } if (paymentFee != decimal.Zero) { amountDetails.Add("handling_fee", paymentFee.FormatInvariant()); } amount.Add("total", total.FormatInvariant()); amount.Add("currency", currencyCode); amount.Add("details", amountDetails); transaction.Add("amount", amount); transaction.Add("item_list", itemList); transaction.Add("invoice_number", session.OrderGuid.ToString()); data.Add("transactions", new List <Dictionary <string, object> > { transaction }); var result = CallApi("POST", "/v1/payments/payment", session.AccessToken, settings, JsonConvert.SerializeObject(data)); if (result.Success && result.Json != null) { result.Id = (string)result.Json.id; } //Logger.InsertLog(LogLevel.Information, "PayPal PLUS", JsonConvert.SerializeObject(data, Formatting.Indented) + "\r\n\r\n" + (result.Json != null ? result.Json.ToString() : "")); return(result); }
protected virtual decimal GetPreselectedPrice(Product product, PriceCalculationContext context, ProductBundleItemData bundleItem, IEnumerable <ProductBundleItemData> bundleItems) { var taxRate = decimal.Zero; var attributesTotalPriceBase = decimal.Zero; var preSelectedPriceAdjustmentBase = decimal.Zero; var isBundle = (product.ProductType == ProductType.BundledProduct); var isBundleItemPricing = (bundleItem != null && bundleItem.Item.BundleProduct.BundlePerItemPricing); var isBundlePricing = (bundleItem != null && !bundleItem.Item.BundleProduct.BundlePerItemPricing); var bundleItemId = (bundleItem == null ? 0 : bundleItem.Item.Id); var selectedAttributes = new NameValueCollection(); var selectedAttributeValues = new List <ProductVariantAttributeValue>(); var attributes = context.Attributes.Load(product.Id); // 1. fill selectedAttributes with initially selected attributes foreach (var attribute in attributes.Where(x => x.ProductVariantAttributeValues.Count > 0 && x.ShouldHaveValues())) { int preSelectedValueId = 0; ProductVariantAttributeValue defaultValue = null; var selectedValueIds = new List <int>(); var pvaValues = attribute.ProductVariantAttributeValues; foreach (var pvaValue in pvaValues) { ProductBundleItemAttributeFilter attributeFilter = null; if (bundleItem.FilterOut(pvaValue, out attributeFilter)) { continue; } if (preSelectedValueId == 0 && attributeFilter != null && attributeFilter.IsPreSelected) { preSelectedValueId = attributeFilter.AttributeValueId; } if (!isBundlePricing && pvaValue.IsPreSelected) { decimal attributeValuePriceAdjustment = GetProductVariantAttributeValuePriceAdjustment(pvaValue); decimal priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, out taxRate); preSelectedPriceAdjustmentBase = decimal.Add(preSelectedPriceAdjustmentBase, priceAdjustmentBase); } } // value pre-selected by a bundle item filter discards the default pre-selection if (preSelectedValueId != 0 && (defaultValue = pvaValues.FirstOrDefault(x => x.Id == preSelectedValueId)) != null) { //defaultValue.IsPreSelected = true; selectedAttributeValues.Add(defaultValue); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, defaultValue.Id, product.Id, bundleItemId); } else { foreach (var value in pvaValues.Where(x => x.IsPreSelected)) { selectedAttributeValues.Add(value); selectedAttributes.AddProductAttribute(attribute.ProductAttributeId, attribute.Id, value.Id, product.Id, bundleItemId); } } } // 2. find attribute combination for selected attributes and merge it if (!isBundle && selectedAttributes.Count > 0) { var attributeXml = selectedAttributes.CreateSelectedAttributesXml(product.Id, attributes, _productAttributeParser, _services.Localization, _downloadService, _catalogSettings, _httpRequestBase, new List <string>(), true, bundleItemId); var combinations = context.AttributeCombinations.Load(product.Id); var selectedCombination = combinations.FirstOrDefault(x => _productAttributeParser.AreProductAttributesEqual(x.AttributesXml, attributeXml)); if (selectedCombination != null && selectedCombination.IsActive && selectedCombination.Price.HasValue) { product.MergedDataValues = new Dictionary <string, object> { { "Price", selectedCombination.Price.Value } }; } } if (_catalogSettings.EnableDynamicPriceUpdate && !isBundlePricing) { if (selectedAttributeValues.Count > 0) { selectedAttributeValues.Each(x => attributesTotalPriceBase += GetProductVariantAttributeValuePriceAdjustment(x)); } else { attributesTotalPriceBase = preSelectedPriceAdjustmentBase; } } if (bundleItem != null) { bundleItem.AdditionalCharge = attributesTotalPriceBase; } var result = GetFinalPrice(product, bundleItems, _services.WorkContext.CurrentCustomer, attributesTotalPriceBase, true, 1, bundleItem, context); return(result); }
/// <summary> /// Formats attributes /// </summary> /// <param name="product">Product</param> /// <param name="attributesXml">Attributes in XML format</param> /// <param name="customer">Customer</param> /// <param name="separator">Separator</param> /// <param name="htmlEncode">A value indicating whether to encode (HTML) values</param> /// <param name="renderPrices">A value indicating whether to render prices</param> /// <param name="renderProductAttributes">A value indicating whether to render product attributes</param> /// <param name="renderGiftCardAttributes">A value indicating whether to render gift card attributes</param> /// <param name="allowHyperlinks">A value indicating whether to HTML hyperink tags could be rendered (if required)</param> /// <returns>Attributes</returns> public virtual string FormatAttributes(Product product, string attributesXml, Customer customer, string separator = "<br />", bool htmlEncode = true, bool renderPrices = true, bool renderProductAttributes = true, bool renderGiftCardAttributes = true, bool allowHyperlinks = true) { var result = new StringBuilder(); //attributes if (renderProductAttributes) { foreach (var attribute in _productAttributeParser.ParseProductAttributeMappings(attributesXml)) { //attributes without values if (!attribute.ShouldHaveValues()) { foreach (var value in _productAttributeParser.ParseValues(attributesXml, attribute.Id)) { var formattedAttribute = string.Empty; if (attribute.AttributeControlType == AttributeControlType.MultilineTextbox) { //multiline textbox var attributeName = _localizationService.GetLocalized(attribute.ProductAttribute, a => a.Name, _workContext.WorkingLanguage.Id); //encode (if required) if (htmlEncode) { attributeName = WebUtility.HtmlEncode(attributeName); } //we never encode multiline textbox input formattedAttribute = $"{attributeName}: {HtmlHelper.FormatText(value, false, true, false, false, false, false)}"; } else if (attribute.AttributeControlType == AttributeControlType.FileUpload) { //file upload Guid.TryParse(value, out var downloadGuid); var download = _downloadService.GetDownloadByGuid(downloadGuid); if (download != null) { var fileName = $"{download.Filename ?? download.DownloadGuid.ToString()}{download.Extension}"; //encode (if required) if (htmlEncode) { fileName = WebUtility.HtmlEncode(fileName); } //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var attributeText = allowHyperlinks ? $"<a href=\"{_webHelper.GetStoreLocation(false)}download/getfileupload/?downloadId={download.DownloadGuid}\" class=\"fileuploadattribute\">{fileName}</a>" : fileName; var attributeName = _localizationService.GetLocalized(attribute.ProductAttribute, a => a.Name, _workContext.WorkingLanguage.Id); //encode (if required) if (htmlEncode) { attributeName = WebUtility.HtmlEncode(attributeName); } formattedAttribute = $"{attributeName}: {attributeText}"; } } else { //other attributes (textbox, datepicker) formattedAttribute = $"{_localizationService.GetLocalized(attribute.ProductAttribute, a => a.Name, _workContext.WorkingLanguage.Id)}: {value}"; //encode (if required) if (htmlEncode) { formattedAttribute = WebUtility.HtmlEncode(formattedAttribute); } } if (string.IsNullOrEmpty(formattedAttribute)) { continue; } if (result.Length > 0) { result.Append(separator); } result.Append(formattedAttribute); } } //product attribute values else { foreach (var attributeValue in _productAttributeParser.ParseProductAttributeValues(attributesXml, attribute.Id)) { var formattedAttribute = $"{_localizationService.GetLocalized(attribute.ProductAttribute, a => a.Name, _workContext.WorkingLanguage.Id)}: {_localizationService.GetLocalized(attributeValue, a => a.Name, _workContext.WorkingLanguage.Id)}"; if (renderPrices) { if (attributeValue.PriceAdjustmentUsePercentage) { if (attributeValue.PriceAdjustment > decimal.Zero) { formattedAttribute += string.Format( _localizationService.GetResource("FormattedAttributes.PriceAdjustment"), "+", attributeValue.PriceAdjustment.ToString("G29"), "%"); } else if (attributeValue.PriceAdjustment < decimal.Zero) { formattedAttribute += string.Format( _localizationService.GetResource("FormattedAttributes.PriceAdjustment"), string.Empty, attributeValue.PriceAdjustment.ToString("G29"), "%"); } } else { var attributeValuePriceAdjustment = _priceCalculationService.GetProductAttributeValuePriceAdjustment(attributeValue, customer); var priceAdjustmentBase = _taxService.GetProductPrice(product, attributeValuePriceAdjustment, customer, out var _); var priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) { formattedAttribute += string.Format( _localizationService.GetResource("FormattedAttributes.PriceAdjustment"), "+", _priceFormatter.FormatPrice(priceAdjustment, false, false), string.Empty); } else if (priceAdjustmentBase < decimal.Zero) { formattedAttribute += string.Format( _localizationService.GetResource("FormattedAttributes.PriceAdjustment"), "-", _priceFormatter.FormatPrice(-priceAdjustment, false, false), string.Empty); } } } //display quantity if (_shoppingCartSettings.RenderAssociatedAttributeValueQuantity && attributeValue.AttributeValueType == AttributeValueType.AssociatedToProduct) { //render only when more than 1 if (attributeValue.Quantity > 1) { formattedAttribute += string.Format(_localizationService.GetResource("ProductAttributes.Quantity"), attributeValue.Quantity); } } //encode (if required) if (htmlEncode) { formattedAttribute = WebUtility.HtmlEncode(formattedAttribute); } if (string.IsNullOrEmpty(formattedAttribute)) { continue; } if (result.Length > 0) { result.Append(separator); } result.Append(formattedAttribute); } } } } //gift cards if (!renderGiftCardAttributes) { return(result.ToString()); } if (!product.IsGiftCard) { return(result.ToString()); } _productAttributeParser.GetGiftCardAttribute(attributesXml, out var giftCardRecipientName, out var giftCardRecipientEmail, out var giftCardSenderName, out var giftCardSenderEmail, out var _); //sender var giftCardFrom = product.GiftCardType == GiftCardType.Virtual ? string.Format(_localizationService.GetResource("GiftCardAttribute.From.Virtual"), giftCardSenderName, giftCardSenderEmail) : string.Format(_localizationService.GetResource("GiftCardAttribute.From.Physical"), giftCardSenderName); //recipient var giftCardFor = product.GiftCardType == GiftCardType.Virtual ? string.Format(_localizationService.GetResource("GiftCardAttribute.For.Virtual"), giftCardRecipientName, giftCardRecipientEmail) : string.Format(_localizationService.GetResource("GiftCardAttribute.For.Physical"), giftCardRecipientName); //encode (if required) if (htmlEncode) { giftCardFrom = WebUtility.HtmlEncode(giftCardFrom); giftCardFor = WebUtility.HtmlEncode(giftCardFor); } if (!string.IsNullOrEmpty(result.ToString())) { result.Append(separator); } result.Append(giftCardFrom); result.Append(separator); result.Append(giftCardFor); return(result.ToString()); }
/// <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 ""; }
/// <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 ""; }