public virtual ActionResult GetCartDetails(int customerId) { if (!_permissionService.Authorize(StandardPermissionProvider.ManageCurrentCarts)) { return(AccessDeniedKendoGridJson()); } 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", ArticleId = sci.ArticleId, Quantity = sci.Quantity, ArticleName = sci.Article.Name, AttributeInfo = _articleAttributeFormatter.FormatAttributes(sci.Article, sci.AttributesXml, sci.Customer), UnitPrice = _priceFormatter.FormatPrice(_taxService.GetArticlePrice(sci.Article, _priceCalculationService.GetUnitPrice(sci), out taxRate)), Total = _priceFormatter.FormatPrice(_taxService.GetArticlePrice(sci.Article, _priceCalculationService.GetSubTotal(sci), out taxRate)), UpdatedOn = _dateTimeHelper.ConvertToUserTime(sci.UpdatedOnUtc, DateTimeKind.Utc) }; return(sciModel); }), Total = cart.Count }; return(Json(gridModel)); }
/// <summary> /// Gets shopping cart subtotal /// </summary> /// <param name="cart">Cart</param> /// <param name="includingTax">A value indicating whether calculated price should include tax</param> /// <param name="discountAmount">Applied discount amount</param> /// <param name="appliedDiscounts">Applied discounts</param> /// <param name="subTotalWithoutDiscount">Sub total (without discount)</param> /// <param name="subTotalWithDiscount">Sub total (with discount)</param> /// <param name="taxRates">Tax rates (of subscription sub total)</param> public virtual void GetShoppingCartSubTotal(IList <ShoppingCartItem> cart, bool includingTax, out decimal discountAmount, out decimal subTotalWithoutDiscount, out decimal subTotalWithDiscount, out SortedDictionary <decimal, decimal> taxRates) { discountAmount = decimal.Zero; subTotalWithoutDiscount = decimal.Zero; subTotalWithDiscount = decimal.Zero; taxRates = new SortedDictionary <decimal, decimal>(); if (!cart.Any()) { return; } //get the customer Customer customer = cart.GetCustomer(); //sub totals decimal subTotalExclTaxWithoutDiscount = decimal.Zero; decimal subTotalInclTaxWithoutDiscount = decimal.Zero; foreach (var shoppingCartItem in cart) { decimal sciSubTotal = _priceCalculationService.GetSubTotal(shoppingCartItem); decimal taxRate; decimal sciExclTax = _taxService.GetArticlePrice(shoppingCartItem.Article, sciSubTotal, false, customer, out taxRate); decimal sciInclTax = _taxService.GetArticlePrice(shoppingCartItem.Article, sciSubTotal, true, customer, out taxRate); subTotalExclTaxWithoutDiscount += sciExclTax; subTotalInclTaxWithoutDiscount += sciInclTax; //tax rates decimal sciTax = sciInclTax - sciExclTax; if (taxRate > decimal.Zero && sciTax > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, sciTax); } else { taxRates[taxRate] = taxRates[taxRate] + sciTax; } } } //checkout attributes if (customer != null) { var checkoutAttributesXml = customer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id); var attributeValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(checkoutAttributesXml); if (attributeValues != null) { foreach (var attributeValue in attributeValues) { decimal taxRate; decimal caExclTax = _taxService.GetCheckoutAttributePrice(attributeValue, false, customer, out taxRate); decimal caInclTax = _taxService.GetCheckoutAttributePrice(attributeValue, true, customer, out taxRate); subTotalExclTaxWithoutDiscount += caExclTax; subTotalInclTaxWithoutDiscount += caInclTax; //tax rates decimal caTax = caInclTax - caExclTax; if (taxRate > decimal.Zero && caTax > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, caTax); } else { taxRates[taxRate] = taxRates[taxRate] + caTax; } } } } } //subtotal without discount subTotalWithoutDiscount = includingTax ? subTotalInclTaxWithoutDiscount : subTotalExclTaxWithoutDiscount; if (subTotalWithoutDiscount < decimal.Zero) { subTotalWithoutDiscount = decimal.Zero; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { subTotalWithoutDiscount = RoundingHelper.RoundPrice(subTotalWithoutDiscount); } //We calculate discount amount on subscription subtotal excl tax (discount first) //calculate discount amount ('Applied to subscription subtotal' discount) decimal discountAmountExclTax = GetSubscriptionSubtotalDiscount(customer, subTotalExclTaxWithoutDiscount); if (subTotalExclTaxWithoutDiscount < discountAmountExclTax) { discountAmountExclTax = subTotalExclTaxWithoutDiscount; } decimal discountAmountInclTax = discountAmountExclTax; //subtotal with discount (excl tax) decimal subTotalExclTaxWithDiscount = subTotalExclTaxWithoutDiscount - discountAmountExclTax; decimal subTotalInclTaxWithDiscount = subTotalExclTaxWithDiscount; //add tax for shopping items & checkout attributes var tempTaxRates = new Dictionary <decimal, decimal>(taxRates); foreach (KeyValuePair <decimal, decimal> kvp in tempTaxRates) { decimal taxRate = kvp.Key; decimal taxValue = kvp.Value; if (taxValue != decimal.Zero) { //discount the tax amount that applies to subtotal items if (subTotalExclTaxWithoutDiscount > decimal.Zero) { decimal discountTax = taxRates[taxRate] * (discountAmountExclTax / subTotalExclTaxWithoutDiscount); discountAmountInclTax += discountTax; taxValue = taxRates[taxRate] - discountTax; if (_shoppingCartSettings.RoundPricesDuringCalculation) { taxValue = RoundingHelper.RoundPrice(taxValue); } taxRates[taxRate] = taxValue; } //subtotal with discount (incl tax) subTotalInclTaxWithDiscount += taxValue; } } if (_shoppingCartSettings.RoundPricesDuringCalculation) { discountAmountInclTax = RoundingHelper.RoundPrice(discountAmountInclTax); discountAmountExclTax = RoundingHelper.RoundPrice(discountAmountExclTax); } if (includingTax) { subTotalWithDiscount = subTotalInclTaxWithDiscount; discountAmount = discountAmountInclTax; } else { subTotalWithDiscount = subTotalExclTaxWithDiscount; discountAmount = discountAmountExclTax; } if (subTotalWithDiscount < decimal.Zero) { subTotalWithDiscount = decimal.Zero; } if (_shoppingCartSettings.RoundPricesDuringCalculation) { subTotalWithDiscount = RoundingHelper.RoundPrice(subTotalWithDiscount); } }
/// <summary> /// Formats attributes /// </summary> /// <param name="article">Article</param> /// <param name="attributesXml">Attributes in XML format</param> /// <param name="customer">Customer</param> /// <param name="serapator">Serapator</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="renderArticleAttributes">A value indicating whether to render article 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(Article article, string attributesXml, Customer customer, string serapator = "<br />", bool htmlEncode = true, bool renderPrices = true, bool renderArticleAttributes = true, bool renderGiftCardAttributes = true, bool allowHyperlinks = true) { var result = new StringBuilder(); //attributes if (renderArticleAttributes) { foreach (var attribute in _articleAttributeParser.ParseArticleAttributeMappings(attributesXml)) { //attributes without values if (!attribute.ShouldHaveValues()) { foreach (var value in _articleAttributeParser.ParseValues(attributesXml, attribute.Id)) { var formattedAttribute = string.Empty; if (attribute.AttributeControlType == AttributeControlType.MultilineTextbox) { //multiline textbox var attributeName = attribute.ArticleAttribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id); //encode (if required) if (htmlEncode) { attributeName = HttpUtility.HtmlEncode(attributeName); } //we never encode multiline textbox input formattedAttribute = string.Format("{0}: {1}", attributeName, HtmlHelper.FormatText(value, false, true, false, false, false, false)); } else if (attribute.AttributeControlType == AttributeControlType.FileUpload) { //file upload Guid downloadGuid; Guid.TryParse(value, out downloadGuid); var download = _downloadService.GetDownloadByGuid(downloadGuid); if (download != null) { var fileName = string.Format("{0}{1}", download.Filename ?? download.DownloadGuid.ToString(), download.Extension); //encode (if required) if (htmlEncode) { fileName = HttpUtility.HtmlEncode(fileName); } //TODO add a method for getting URL (use routing because it handles all SEO friendly URLs) var attributeText = allowHyperlinks ? string.Format("<a href=\"{0}download/getfileupload/?downloadId={1}\" class=\"fileuploadattribute\">{2}</a>", _webHelper.GetStoreLocation(false), download.DownloadGuid, fileName) : fileName; var attributeName = attribute.ArticleAttribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id); //encode (if required) if (htmlEncode) { attributeName = HttpUtility.HtmlEncode(attributeName); } formattedAttribute = string.Format("{0}: {1}", attributeName, attributeText); } } else { //other attributes (textbox, datepicker) formattedAttribute = string.Format("{0}: {1}", attribute.ArticleAttribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), value); //encode (if required) if (htmlEncode) { formattedAttribute = HttpUtility.HtmlEncode(formattedAttribute); } } if (!string.IsNullOrEmpty(formattedAttribute)) { if (result.Length > 0) { result.Append(serapator); } result.Append(formattedAttribute); } } } //article attribute values else { foreach (var attributeValue in _articleAttributeParser.ParseArticleAttributeValues(attributesXml, attribute.Id)) { var formattedAttribute = string.Format("{0}: {1}", attribute.ArticleAttribute.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id), attributeValue.GetLocalized(a => a.Name, _workContext.WorkingLanguage.Id)); if (renderPrices) { decimal taxRate; var attributeValuePriceAdjustment = _priceCalculationService.GetArticleAttributeValuePriceAdjustment(attributeValue); var priceAdjustmentBase = _taxService.GetArticlePrice(article, attributeValuePriceAdjustment, customer, out taxRate); var priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > 0) { formattedAttribute += string.Format(" [+{0}]", _priceFormatter.FormatPrice(priceAdjustment, false, false)); } else if (priceAdjustmentBase < decimal.Zero) { formattedAttribute += string.Format(" [-{0}]", _priceFormatter.FormatPrice(-priceAdjustment, false, false)); } } //display quantity if (_shoppingCartSettings.RenderAssociatedAttributeValueQuantity && attributeValue.AttributeValueType == AttributeValueType.AssociatedToArticle) { //render only when more than 1 if (attributeValue.Quantity > 1) { formattedAttribute += string.Format(_localizationService.GetResource("ArticleAttributes.Quantity"), attributeValue.Quantity); } } //encode (if required) if (htmlEncode) { formattedAttribute = HttpUtility.HtmlEncode(formattedAttribute); } if (!string.IsNullOrEmpty(formattedAttribute)) { if (result.Length > 0) { result.Append(serapator); } result.Append(formattedAttribute); } } } } } return(result.ToString()); }