/// <summary> /// Gets a value indicating whether shipping is free /// </summary> /// <param name="cart">Cart</param> /// <returns>A value indicating whether shipping is free</returns> public virtual bool IsFreeShipping(IList<ShoppingCartItem> cart) { Customer customer = cart.GetCustomer(); if (customer != null) { //check whether customer is in a customer role with free shipping applied var customerRoles = customer.CustomerRoles.Where(cr => cr.Active); foreach (var customerRole in customerRoles) if (customerRole.FreeShipping) return true; } bool shoppingCartRequiresShipping = cart.RequiresShipping(); if (!shoppingCartRequiresShipping) return true; //check whether all shopping cart items are marked as free shipping bool allItemsAreFreeShipping = true; foreach (var sc in cart) { if (sc.IsShipEnabled && !sc.IsFreeShipping) { allItemsAreFreeShipping = false; break; } } if (allItemsAreFreeShipping) return true; //free shipping over $X if (_shippingSettings.FreeShippingOverXEnabled) { //check whether we have subtotal enough to have free shipping decimal subTotalDiscountAmount = decimal.Zero; Discount subTotalAppliedDiscount = null; decimal subTotalWithoutDiscountBase = decimal.Zero; decimal subTotalWithDiscountBase = decimal.Zero; GetShoppingCartSubTotal(cart, _shippingSettings.FreeShippingOverXIncludingTax, out subTotalDiscountAmount, out subTotalAppliedDiscount, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); if (subTotalWithDiscountBase > _shippingSettings.FreeShippingOverXValue) return true; } //otherwise, return false return false; }
/// <summary> /// Returns a value indicating whether payment method should be hidden during checkout /// </summary> /// <param name="cart">Shoping cart</param> /// <returns>true - hide; false - display.</returns> public bool HidePaymentMethod(IList<ShoppingCartItem> cart) { //you can put any logic here //for example, hide this payment method if all products in the cart are downloadable //or hide this payment method if current customer is from certain country if (_purchaseOrderPaymentSettings.ShippableProductRequired && !cart.RequiresShipping()) return true; return false; }
public virtual OnePageCheckoutModel PrepareOnePageCheckoutModel(IList <ShoppingCartItem> cart) { if (cart == null) { throw new ArgumentNullException("cart"); } var model = new OnePageCheckoutModel { ShippingRequired = cart.RequiresShipping(), DisableBillingAddressCheckoutStep = _orderSettings.DisableBillingAddressCheckoutStep }; return(model); }
/// <summary> /// Prepare one page checkout model /// </summary> /// <param name="cart">Cart</param> /// <returns>One page checkout model</returns> public virtual OnePageCheckoutModel PrepareOnePageCheckoutModel(IList <ShoppingCartItem> cart) { if (cart == null) { throw new ArgumentNullException(nameof(cart)); } var model = new OnePageCheckoutModel { ShippingRequired = cart.RequiresShipping(_productService, _productAttributeParser), DisableBillingAddressCheckoutStep = _orderSettings.DisableBillingAddressCheckoutStep, BillingAddress = PrepareBillingAddressModel(cart, prePopulateNewAddressWithCustomerFields: true) }; return(model); }
/// <summary> /// Prepare billing address model /// </summary> /// <param name="cart">Cart</param> /// <param name="selectedCountryId">Selected country identifier</param> /// <param name="prePopulateNewAddressWithCustomerFields">Pre populate new address with customer fields</param> /// <param name="overrideAttributesXml">Override attributes xml</param> /// <returns>Billing address model</returns> public virtual CheckoutBillingAddressModel PrepareBillingAddressModel(IList <ShoppingCartItem> cart, int?selectedCountryId = null, bool prePopulateNewAddressWithCustomerFields = false, string overrideAttributesXml = "") { var model = new CheckoutBillingAddressModel { ShipToSameAddressAllowed = _shippingSettings.ShipToSameAddress && cart.RequiresShipping(_productService, _productAttributeParser), //allow customers to enter (choose) a shipping address if "Disable Billing address step" setting is enabled ShipToSameAddress = !_orderSettings.DisableBillingAddressCheckoutStep }; //existing addresses var addresses = _workContext.CurrentCustomer.Addresses .Where(a => a.Country == null || (//published a.Country.Published && //allow billing a.Country.AllowsBilling && //enabled for the current store _storeMappingService.Authorize(a.Country))) .ToList(); foreach (var address in addresses) { var addressModel = new AddressModel(); _addressModelFactory.PrepareAddressModel(addressModel, address: address, excludeProperties: false, addressSettings: _addressSettings); model.ExistingAddresses.Add(addressModel); } //new address model.BillingNewAddress.CountryId = selectedCountryId; _addressModelFactory.PrepareAddressModel(model.BillingNewAddress, address: null, excludeProperties: false, addressSettings: _addressSettings, loadCountries: () => _countryService.GetAllCountriesForBilling(_workContext.WorkingLanguage.Id), prePopulateWithCustomerFields: prePopulateNewAddressWithCustomerFields, customer: _workContext.CurrentCustomer, overrideAttributesXml: overrideAttributesXml); return(model); }
/// <summary> /// Returns a value indicating whether payment method should be hidden during checkout /// </summary> /// <param name="cart">Shoping cart</param> /// <returns>true - hide; false - display.</returns> public bool HidePaymentMethod(IList <ShoppingCartItem> cart) { //edit here by amal to do 4000 COD decimal total = 0; foreach (var a in cart) { total += a.Product.Price * a.Quantity; } if (total >= 4000) { //you can put any logic here //for example, hide this payment method if all products in the cart are downloadable //or hide this payment method if current customer is from certain country return(true); } return(_cashOnDeliveryPaymentSettings.ShippableProductRequired && !cart.RequiresShipping()); }
/// <summary> /// Gets a value indicating whether shipping is free /// </summary> /// <param name="cart">Cart</param> /// <returns>A value indicating whether shipping is free</returns> public virtual bool IsFreeShipping(IList <ShoppingCartItem> cart) { Customer customer = cart.GetCustomer(); if (customer != null) { //check whether customer is in a customer role with free shipping applied var customerRoles = customer.CustomerRoles.Where(cr => cr.Active); foreach (var customerRole in customerRoles) { if (customerRole.FreeShipping) { return(true); } } } bool shoppingCartRequiresShipping = cart.RequiresShipping(); if (!shoppingCartRequiresShipping) { return(true); } //check whether all shopping cart items are marked as free shipping bool allItemsAreFreeShipping = true; foreach (var sc in cart) { if (sc.IsShipEnabled && !sc.IsFreeShipping) { allItemsAreFreeShipping = false; break; } } if (allItemsAreFreeShipping) { return(true); } //otherwise, return false return(false); }
/// <summary> /// Prepare one page checkout model /// </summary> /// <param name="cart">Cart</param> /// <returns>One page checkout model</returns> public virtual OnePageCheckoutModel PrepareOnePageCheckoutModel(IList <ShoppingCartItem> cart) { if (cart == null) { throw new ArgumentNullException(nameof(cart)); } var filterByCountryId = 0; if (_addressSettings.CountryEnabled && _workContext.CurrentCustomer.BillingAddress != null && _workContext.CurrentCustomer.BillingAddress.Country != null) { filterByCountryId = _workContext.CurrentCustomer.BillingAddress.Country.Id; } IPaymentMethod paymentMethod; var paymentMethodSystemName = _workContext.CurrentCustomer .GetAttribute <string>(SystemCustomerAttributeNames.SelectedPaymentMethod, _genericAttributeService, _storeContext.CurrentStore.Id); if (!string.IsNullOrEmpty(paymentMethodSystemName)) { paymentMethod = _paymentService.LoadPaymentMethodBySystemName(paymentMethodSystemName); } else { paymentMethod = _paymentService .LoadActivePaymentMethods(_workContext.CurrentCustomer, _storeContext.CurrentStore.Id, filterByCountryId).FirstOrDefault(); } var model = new OnePageCheckoutModel { ShippingRequired = cart.RequiresShipping(_productService, _productAttributeParser), DisableBillingAddressCheckoutStep = _orderSettings.DisableBillingAddressCheckoutStep, BillingAddress = PrepareBillingAddressModel(cart, prePopulateNewAddressWithCustomerFields: true), ShippingAddress = PrepareShippingAddressModel(prePopulateNewAddressWithCustomerFields: true), }; return(model); }
protected virtual CheckoutBillingAddressModel PrepareBillingAddressModel( IList <ShoppingCartItem> cart, string selectedCountryId = null, bool prePopulateNewAddressWithCustomerFields = false, string overrideAttributesXml = "") { var model = new CheckoutBillingAddressModel(); model.ShipToSameAddressAllowed = _shippingSettings.ShipToSameAddress && cart.RequiresShipping(); model.ShipToSameAddress = true; //existing addresses var addresses = _workContext.CurrentCustomer.Addresses .Where(a => a.CountryId == "" || (_countryService.GetCountryById(a.CountryId) != null ? _countryService.GetCountryById(a.CountryId).AllowsBilling : false) ) .Where(a => a.CountryId == "" || _storeMappingService.Authorize((_countryService.GetCountryById(a.CountryId)) )) .ToList(); foreach (var address in addresses) { var addressModel = new AddressModel(); _addressWebService.PrepareModel(model: addressModel, address: address, excludeProperties: false); model.ExistingAddresses.Add(addressModel); } //new address model.NewAddress.CountryId = selectedCountryId; _addressWebService.PrepareModel(model: model.NewAddress, address: null, excludeProperties: false, loadCountries: () => _countryService.GetAllCountriesForBilling(_workContext.WorkingLanguage.Id), prePopulateWithCustomerFields: prePopulateNewAddressWithCustomerFields, customer: _workContext.CurrentCustomer, overrideAttributesXml: overrideAttributesXml ); return(model); }
/// <summary> /// PrepareOrderTotalsModel: /// </summary> /// <param name="cart"></param> /// <param name="isEditable"></param> /// <returns></returns> public virtual decimal PrepareOrderTotalsModel(IList <ShoppingCartItem> cart, bool isEditable) { var model = new OrderTotalsModel(); model.IsEditable = isEditable; if (cart.Count > 0) { //subtotal decimal orderSubTotalDiscountAmountBase; Discount orderSubTotalAppliedDiscount; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; var subTotalIncludingTax = _workContext.TaxDisplayType == TaxDisplayType.IncludingTax && !_taxSettings.ForceTaxExclusionFromOrderSubtotal; _orderTotalCalculationService.GetShoppingCartSubTotal(cart, subTotalIncludingTax, out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); decimal subtotalBase = subTotalWithoutDiscountBase; decimal subtotal = _currencyService.ConvertFromPrimaryStoreCurrency(subtotalBase, _workContext.WorkingCurrency); model.SubTotal = _priceFormatter.FormatPrice(subtotal, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); if (orderSubTotalDiscountAmountBase > decimal.Zero) { decimal orderSubTotalDiscountAmount = _currencyService.ConvertFromPrimaryStoreCurrency(orderSubTotalDiscountAmountBase, _workContext.WorkingCurrency); model.SubTotalDiscount = _priceFormatter.FormatPrice(-orderSubTotalDiscountAmount, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); model.AllowRemovingSubTotalDiscount = orderSubTotalAppliedDiscount != null && orderSubTotalAppliedDiscount.RequiresCouponCode && !String.IsNullOrEmpty(orderSubTotalAppliedDiscount.CouponCode) && model.IsEditable; } //shipping info model.RequiresShipping = cart.RequiresShipping(); if (model.RequiresShipping) { decimal?shoppingCartShippingBase = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart); if (shoppingCartShippingBase.HasValue) { decimal shoppingCartShipping = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, _workContext.WorkingCurrency); model.Shipping = _priceFormatter.FormatShippingPrice(shoppingCartShipping, true); //selected shipping method var shippingOption = _workContext.CurrentCustomer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (shippingOption != null) { model.SelectedShippingMethod = shippingOption.Name; } } } //payment method fee var paymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute <string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id); decimal paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethodSystemName); decimal paymentMethodAdditionalFeeWithTaxBase = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, _workContext.CurrentCustomer); if (paymentMethodAdditionalFeeWithTaxBase > decimal.Zero) { decimal paymentMethodAdditionalFeeWithTax = _currencyService.ConvertFromPrimaryStoreCurrency(paymentMethodAdditionalFeeWithTaxBase, _workContext.WorkingCurrency); model.PaymentMethodAdditionalFee = _priceFormatter.FormatPaymentMethodAdditionalFee(paymentMethodAdditionalFeeWithTax, true); } //tax bool displayTax = true; bool displayTaxRates = true; if (_taxSettings.HideTaxInOrderSummary && _workContext.TaxDisplayType == TaxDisplayType.IncludingTax) { displayTax = false; displayTaxRates = false; } else { SortedDictionary <decimal, decimal> taxRates; decimal shoppingCartTaxBase = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates); decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, _workContext.WorkingCurrency); if (shoppingCartTaxBase == 0 && _taxSettings.HideZeroTax) { displayTax = false; displayTaxRates = false; } else { displayTaxRates = _taxSettings.DisplayTaxRates && taxRates.Count > 0; displayTax = !displayTaxRates; model.Tax = _priceFormatter.FormatPrice(shoppingCartTax, true, false); foreach (var tr in taxRates) { model.TaxRates.Add(new OrderTotalsModel.TaxRate { Rate = _priceFormatter.FormatTaxRate(tr.Key), Value = _priceFormatter.FormatPrice(_currencyService.ConvertFromPrimaryStoreCurrency(tr.Value, _workContext.WorkingCurrency), true, false), }); } } } model.DisplayTaxRates = displayTaxRates; model.DisplayTax = displayTax; //total decimal orderTotalDiscountAmountBase; Discount orderTotalAppliedDiscount; List <AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; decimal?shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, out orderTotalDiscountAmountBase, out orderTotalAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); return(_currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotalBase.Value, _workContext.WorkingCurrency)); } return(decimal.Zero); }
/// <summary> /// Returns a value indicating whether payment method should be hidden during checkout /// </summary> /// <param name="cart">Shoping cart</param> /// <returns>true - hide; false - display.</returns> public bool HidePaymentMethod(IList <ShoppingCartItem> cart) { //you can put any logic here //for example, hide this payment method if all products in the cart are downloadable //or hide this payment method if current customer is from certain country // amsfcii int maxValue = 5000; var result = (cart.OrderTotal > 5000) && _cashOnDeliveryPaymentSettings.ShippableProductRequired && !cart.RequiresShipping(); if (result) { return(true); } return(false); }
/// <summary> /// Validates whether this shopping cart is valid /// </summary> /// <param name="shoppingCart">Shopping cart</param> /// <param name="checkoutAttributes">Checkout attributes</param> /// <param name="validateCheckoutAttributes">A value indicating whether to validate checkout attributes</param> /// <returns>Warnings</returns> public virtual IList <string> GetShoppingCartWarnings(IList <ShoppingCartItem> shoppingCart, string checkoutAttributes, bool validateCheckoutAttributes) { var warnings = new List <string>(); bool hasStandartProducts = false; bool hasRecurringProducts = false; foreach (var sci in shoppingCart) { var productVariant = sci.ProductVariant; if (productVariant == null) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.CannotLoadProductVariant"), sci.ProductVariantId)); return(warnings); } if (productVariant.IsRecurring) { hasRecurringProducts = true; } else { hasStandartProducts = true; } } //don't mix standard and recurring products if (hasStandartProducts && hasRecurringProducts) { warnings.Add(_localizationService.GetResource("ShoppingCart.CannotMixStandardAndAutoshipProducts")); } //recurring cart validation if (hasRecurringProducts) { int cycleLength = 0; RecurringProductCyclePeriod cyclePeriod = RecurringProductCyclePeriod.Days; int totalCycles = 0; string cyclesError = shoppingCart.GetRecurringCycleInfo(out cycleLength, out cyclePeriod, out totalCycles); if (!string.IsNullOrEmpty(cyclesError)) { warnings.Add(cyclesError); return(warnings); } } //validate checkout attributes if (validateCheckoutAttributes) { //selected attributes var ca1Collection = _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttributes); //existing checkout attributes var ca2Collection = _checkoutAttributeService.GetAllCheckoutAttributes(); if (!shoppingCart.RequiresShipping()) { //remove attributes which require shippable products ca2Collection = ca2Collection.RemoveShippableAttributes(); } foreach (var ca2 in ca2Collection) { if (ca2.IsRequired) { bool found = false; //selected checkout attributes foreach (var ca1 in ca1Collection) { if (ca1.Id == ca2.Id) { var caValuesStr = _checkoutAttributeParser.ParseValues(checkoutAttributes, ca1.Id); foreach (string str1 in caValuesStr) { if (!String.IsNullOrEmpty(str1.Trim())) { found = true; break; } } } } //if not found if (!found) { if (!string.IsNullOrEmpty(ca2.GetLocalized(a => a.TextPrompt))) { warnings.Add(ca2.GetLocalized(a => a.TextPrompt)); } else { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.SelectAttribute"), ca2.GetLocalized(a => a.Name))); } } } } } return(warnings); }
protected virtual void PrepareShippingCartModel(ShoppingCartModel model, IList <ShoppingCartItem> cart, IList <ShippingCart> shippingCarts, IList <ShippingCartItem> shippingCartItems, bool isEditable = true, bool validateCheckoutAttributes = false, bool prepareEstimateShippingIfEnabled = true, bool setEstimateShippingDefaultAddress = true, bool prepareAndDisplayOrderReviewData = false) { if (cart == null) { throw new ArgumentNullException("cart"); } if (model == null) { throw new ArgumentNullException("model"); } model.OnePageCheckoutEnabled = _orderSettings.OnePageCheckoutEnabled; if (cart.Count == 0) { return; } #region Simple properties model.IsEditable = isEditable; model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart; model.ShowSku = _catalogSettings.ShowProductSku; var checkoutAttributesXml = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id); model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(checkoutAttributesXml, _workContext.CurrentCustomer); bool minOrderSubtotalAmountOk = _orderProcessingService.ValidateMinOrderSubtotalAmount(cart); if (!minOrderSubtotalAmountOk) { decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); model.MinOrderSubtotalWarning = string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false)); } model.TermsOfServiceOnShoppingCartPage = _orderSettings.TermsOfServiceOnShoppingCartPage; model.TermsOfServiceOnOrderConfirmPage = _orderSettings.TermsOfServiceOnOrderConfirmPage; //gift card and gift card boxes model.DiscountBox.Display = _shoppingCartSettings.ShowDiscountBox; var discountCouponCode = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.DiscountCouponCode); var discount = _discountService.GetDiscountByCouponCode(discountCouponCode); if (discount != null && discount.RequiresCouponCode && _discountService.IsDiscountValid(discount, _workContext.CurrentCustomer)) { model.DiscountBox.CurrentCode = discount.CouponCode; } model.GiftCardBox.Display = _shoppingCartSettings.ShowGiftCardBox; //cart warnings var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, checkoutAttributesXml, validateCheckoutAttributes); foreach (var warning in cartWarnings) { model.Warnings.Add(warning); } #endregion #region Checkout attributes var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(_storeContext.CurrentStore.Id, !cart.RequiresShipping()); foreach (var attribute in checkoutAttributes) { var attributeModel = new ShoppingCartModel.CheckoutAttributeModel { Id = attribute.Id, Name = attribute.GetLocalized(x => x.Name), TextPrompt = attribute.GetLocalized(x => x.TextPrompt), IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, DefaultValue = attribute.DefaultValue }; if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions)) { attributeModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .ToList(); } if (attribute.ShouldHaveValues()) { //values var attributeValues = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id); foreach (var attributeValue in attributeValues) { var attributeValueModel = new ShoppingCartModel.CheckoutAttributeValueModel { Id = attributeValue.Id, Name = attributeValue.GetLocalized(x => x.Name), ColorSquaresRgb = attributeValue.ColorSquaresRgb, IsPreSelected = attributeValue.IsPreSelected, }; attributeModel.Values.Add(attributeValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(attributeValue); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) { attributeValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment); } else if (priceAdjustmentBase < decimal.Zero) { attributeValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment); } } } } //set already selected attributes var selectedCheckoutAttributes = _workContext.CurrentCustomer.GetAttribute <string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id); switch (attribute.AttributeControlType) { case AttributeControlType.DropdownList: case AttributeControlType.RadioList: case AttributeControlType.Checkboxes: case AttributeControlType.ColorSquares: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { //clear default selection foreach (var item in attributeModel.Values) { item.IsPreSelected = false; } //select new values var selectedValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes); foreach (var attributeValue in selectedValues) { foreach (var item in attributeModel.Values) { if (attributeValue.Id == item.Id) { item.IsPreSelected = true; } } } } } break; case AttributeControlType.ReadonlyCheckboxes: { //do nothing //values are already pre-set } break; case AttributeControlType.TextBox: case AttributeControlType.MultilineTextbox: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (enteredText.Count > 0) { attributeModel.DefaultValue = enteredText[0]; } } } break; case AttributeControlType.Datepicker: { //keep in mind my that the code below works only in the current culture var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (selectedDateStr.Count > 0) { DateTime selectedDate; if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture, DateTimeStyles.None, out selectedDate)) { //successfully parsed attributeModel.SelectedDay = selectedDate.Day; attributeModel.SelectedMonth = selectedDate.Month; attributeModel.SelectedYear = selectedDate.Year; } } } break; default: break; } model.CheckoutAttributes.Add(attributeModel); } #endregion #region Cart items foreach (var sci in cart) { var cartItemModel = new ShoppingCartModel.ShoppingCartItemModel { Id = sci.Id, Sku = sci.Product.FormatSku(sci.AttributesXml, _productAttributeParser), ProductId = sci.Product.Id, ProductName = sci.Product.GetLocalized(x => x.Name), ProductSeName = sci.Product.GetSeName(), Quantity = sci.Quantity, AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.Product, sci.AttributesXml), }; //allow editing? //1. setting enabled? //2. simple product? //3. has attribute or gift card? //4. visible individually? cartItemModel.AllowItemEditing = _shoppingCartSettings.AllowCartItemEditing && sci.Product.ProductType == ProductType.SimpleProduct && (!String.IsNullOrEmpty(cartItemModel.AttributeInfo) || sci.Product.IsGiftCard) && sci.Product.VisibleIndividually; //allowed quantities var allowedQuantities = sci.Product.ParseAllowedQuantities(); foreach (var qty in allowedQuantities) { cartItemModel.AllowedQuantities.Add(new SelectListItem { Text = qty.ToString(), Value = qty.ToString(), Selected = sci.Quantity == qty }); } //recurring info if (sci.Product.IsRecurring) { cartItemModel.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"), sci.Product.RecurringCycleLength, sci.Product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext)); } //rental info if (sci.Product.IsRental) { var rentalStartDate = sci.RentalStartDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalStartDateUtc.Value) : ""; var rentalEndDate = sci.RentalEndDateUtc.HasValue ? sci.Product.FormatRentalDate(sci.RentalEndDateUtc.Value) : ""; cartItemModel.RentalInfo = string.Format(_localizationService.GetResource("ShoppingCart.Rental.FormattedDate"), rentalStartDate, rentalEndDate); } //unit prices if (sci.Product.CallForPrice) { cartItemModel.UnitPrice = _localizationService.GetResource("Products.CallForPrice"); } else { decimal taxRate; decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci), out taxRate); decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency); cartItemModel.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount); } //subtotal, discount if (sci.Product.CallForPrice) { cartItemModel.SubTotal = _localizationService.GetResource("Products.CallForPrice"); } else { //sub total Discount scDiscount; decimal shoppingCartItemDiscountBase; decimal taxRate; decimal shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, true, out shoppingCartItemDiscountBase, out scDiscount), out taxRate); decimal shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency); cartItemModel.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount); //display an applied discount amount if (scDiscount != null) { shoppingCartItemDiscountBase = _taxService.GetProductPrice(sci.Product, shoppingCartItemDiscountBase, out taxRate); if (shoppingCartItemDiscountBase > decimal.Zero) { decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency); cartItemModel.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount); } } } //picture if (_shoppingCartSettings.ShowProductImagesOnShoppingCart) { cartItemModel.Picture = PrepareCartItemPictureModel(sci, _mediaSettings.CartThumbPictureSize, true, cartItemModel.ProductName); } //item warnings var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings( _workContext.CurrentCustomer, sci.ShoppingCartType, sci.Product, sci.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.RentalStartDateUtc, sci.RentalEndDateUtc, sci.Quantity, false); foreach (var warning in itemWarnings) { cartItemModel.Warnings.Add(warning); } //shipping item var existsShippingItems = shippingCartItems.Where(c => c.ShoppingCartItemId == sci.Id).ToList(); for (int i = 0; i < sci.Quantity; i++) { var existsShippingItem = existsShippingItems.FirstOrDefault(c => c.ShippingCartPosition == i); var shippingCartItemModel = new ShoppingCartModel.ShippingCartItemModel { RecipientName = existsShippingItem != null ? existsShippingItem.ShippingCart.RecipientName : string.Empty, ShippingCartPosition = i }; cartItemModel.ShippingCartItems.Add(shippingCartItemModel); } model.Items.Add(cartItemModel); } #endregion #region ShippingCartItems model.RecipientNames = shippingCarts.Select(c => c.RecipientName).ToList(); if (model.RecipientNames.Contains(MySelf) && model.RecipientNames.IndexOf(MySelf) != 0) { model.RecipientNames.Remove(MySelf); } if (!model.RecipientNames.Contains(MySelf)) { model.RecipientNames.Insert(0, MySelf); } #endregion #region Button payment methods var paymentMethods = _paymentService .LoadActivePaymentMethods(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id) .Where(pm => pm.PaymentMethodType == PaymentMethodType.Button) .Where(pm => !pm.HidePaymentMethod(cart)) .ToList(); foreach (var pm in paymentMethods) { if (cart.IsRecurring() && pm.RecurringPaymentType == RecurringPaymentType.NotSupported) { continue; } string actionName; string controllerName; RouteValueDictionary routeValues; pm.GetPaymentInfoRoute(out actionName, out controllerName, out routeValues); model.ButtonPaymentMethodActionNames.Add(actionName); model.ButtonPaymentMethodControllerNames.Add(controllerName); model.ButtonPaymentMethodRouteValues.Add(routeValues); } #endregion #region Order review data if (prepareAndDisplayOrderReviewData) { model.OrderReviewData.Display = true; //billing info var billingAddress = _workContext.CurrentCustomer.BillingAddress; if (billingAddress != null) { model.OrderReviewData.BillingAddress.PrepareModel( address: billingAddress, excludeProperties: false, addressSettings: _addressSettings, addressAttributeFormatter: _addressAttributeFormatter); } //shipping info if (cart.RequiresShipping()) { model.OrderReviewData.IsShippable = true; if (_shippingSettings.AllowPickUpInStore) { model.OrderReviewData.SelectedPickUpInStore = _workContext.CurrentCustomer.GetAttribute <bool>(SystemCustomerAttributeNames.SelectedPickUpInStore, _storeContext.CurrentStore.Id); } if (!model.OrderReviewData.SelectedPickUpInStore) { var shippingAddress = _workContext.CurrentCustomer.ShippingAddress; if (shippingAddress != null) { model.OrderReviewData.ShippingAddress.PrepareModel( address: shippingAddress, excludeProperties: false, addressSettings: _addressSettings, addressAttributeFormatter: _addressAttributeFormatter); } } //selected shipping method var shippingOption = _workContext.CurrentCustomer.GetAttribute <ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (shippingOption != null) { model.OrderReviewData.ShippingMethod = shippingOption.Name; } } //payment info var selectedPaymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute <string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id); var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(selectedPaymentMethodSystemName); model.OrderReviewData.PaymentMethod = paymentMethod != null?paymentMethod.GetLocalizedFriendlyName(_localizationService, _workContext.WorkingLanguage.Id) : ""; //custom values var processPaymentRequest = _httpContext.Session["OrderPaymentInfo"] as ProcessPaymentRequest; if (processPaymentRequest != null) { model.OrderReviewData.CustomValues = processPaymentRequest.CustomValues; } } #endregion }
/// <summary> /// Validates whether this shopping cart is valid /// </summary> /// <param name="shoppingCart">Shopping cart</param> /// <param name="checkoutAttributesXml">Checkout attributes in XML format</param> /// <param name="validateCheckoutAttributes">A value indicating whether to validate checkout attributes</param> /// <returns>Warnings</returns> public virtual IList<string> GetShoppingCartWarnings(IList<ShoppingCartItem> shoppingCart, string checkoutAttributesXml, bool validateCheckoutAttributes) { var warnings = new List<string>(); bool hasStandartProducts = false; bool hasRecurringProducts = false; foreach (var sci in shoppingCart) { var product = sci.Product; if (product == null) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.CannotLoadProduct"), sci.ProductId)); return warnings; } if (product.IsRecurring) hasRecurringProducts = true; else hasStandartProducts = true; } //don't mix standard and recurring products if (hasStandartProducts && hasRecurringProducts) warnings.Add(_localizationService.GetResource("ShoppingCart.CannotMixStandardAndAutoshipProducts")); //recurring cart validation if (hasRecurringProducts) { int cycleLength; RecurringProductCyclePeriod cyclePeriod; int totalCycles; string cyclesError = shoppingCart.GetRecurringCycleInfo(_localizationService, out cycleLength, out cyclePeriod, out totalCycles); if (!string.IsNullOrEmpty(cyclesError)) { warnings.Add(cyclesError); return warnings; } } //validate checkout attributes if (validateCheckoutAttributes) { //selected attributes var attributes1 = _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttributesXml); //existing checkout attributes var attributes2 = _checkoutAttributeService.GetAllCheckoutAttributes(_storeContext.CurrentStore.ID, !shoppingCart.RequiresShipping()); foreach (var a2 in attributes2) { if (a2.IsRequired) { bool found = false; //selected checkout attributes foreach (var a1 in attributes1) { if (a1.ID == a2.ID) { var attributeValuesStr = _checkoutAttributeParser.ParseValues(checkoutAttributesXml, a1.ID); foreach (string str1 in attributeValuesStr) if (!String.IsNullOrEmpty(str1.Trim())) { found = true; break; } } } //if not found if (!found) { if (!string.IsNullOrEmpty(a2.GetLocalized(a => a.TextPrompt))) warnings.Add(a2.GetLocalized(a => a.TextPrompt)); else warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.SelectAttribute"), a2.GetLocalized(a => a.Name))); } } } //now validation rules //minimum length foreach (var ca in attributes2) { if (ca.ValidationMinLength.HasValue) { if (ca.AttributeControlType == AttributeControlType.TextBox || ca.AttributeControlType == AttributeControlType.MultilineTextbox) { var valuesStr = _checkoutAttributeParser.ParseValues(checkoutAttributesXml, ca.ID); var enteredText = valuesStr.FirstOrDefault(); int enteredTextLength = String.IsNullOrEmpty(enteredText) ? 0 : enteredText.Length; if (ca.ValidationMinLength.Value > enteredTextLength) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.TextboxMinimumLength"), ca.GetLocalized(a => a.Name), ca.ValidationMinLength.Value)); } } } //maximum length if (ca.ValidationMaxLength.HasValue) { if (ca.AttributeControlType == AttributeControlType.TextBox || ca.AttributeControlType == AttributeControlType.MultilineTextbox) { var valuesStr = _checkoutAttributeParser.ParseValues(checkoutAttributesXml, ca.ID); var enteredText = valuesStr.FirstOrDefault(); int enteredTextLength = String.IsNullOrEmpty(enteredText) ? 0 : enteredText.Length; if (ca.ValidationMaxLength.Value < enteredTextLength) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.TextboxMaximumLength"), ca.GetLocalized(a => a.Name), ca.ValidationMaxLength.Value)); } } } } } return warnings; }
/// <summary> /// Removes checkout attributes which cannot be applied to the current cart and returns an update attributes in XML format /// </summary> /// <param name="attributesXml">Attributes in XML format</param> /// <param name="cart">Shopping cart items</param> /// <returns>Updated attributes in XML format</returns> public virtual string EnsureOnlyActiveAttributes(string attributesXml, IList<ShoppingCartItem> cart) { if (String.IsNullOrEmpty(attributesXml)) return attributesXml; var result = attributesXml; //removing "shippable" checkout attributes if there's no any shippable products in the cart if (!cart.RequiresShipping()) { //find attribute IDs to remove var checkoutAttributeIdsToRemove = new List<int>(); var attributes = ParseCheckoutAttributes(attributesXml); foreach (var ca in attributes) if (ca.ShippableProductRequired) checkoutAttributeIdsToRemove.Add(ca.Id); //remove them from XML try { var xmlDoc = new XmlDocument(); xmlDoc.LoadXml(attributesXml); var nodesToRemove = new List<XmlNode>(); foreach (XmlNode node in xmlDoc.SelectNodes(@"//Attributes/CheckoutAttribute")) { if (node.Attributes != null && node.Attributes["ID"] != null) { string str1 = node.Attributes["ID"].InnerText.Trim(); int id; if (int.TryParse(str1, out id)) { if (checkoutAttributeIdsToRemove.Contains(id)) { nodesToRemove.Add(node); } } } } foreach(var node in nodesToRemove) { node.ParentNode.RemoveChild(node); } result = xmlDoc.OuterXml; } catch (Exception exc) { Debug.Write(exc.ToString()); } } return result; }
/// <summary> /// Post cart to google /// </summary> /// <param name="req">Pre-generated request</param> /// <param name="cart">Shopping cart</param> /// <returns>Response</returns> public GCheckoutResponse PostCartToGoogle(CheckoutShoppingCartRequest req, IList<Core.Domain.Orders.ShoppingCartItem> cart) { //there's no need to round prices (Math.Round(,2)) because GCheckout library does it for us //items foreach (Core.Domain.Orders.ShoppingCartItem sci in cart) { var productVariant = sci.ProductVariant; if (productVariant != null) { decimal taxRate = decimal.Zero; string description = _productAttributeFormatter.FormatAttributes(productVariant, sci.AttributesXml, _workContext.CurrentCustomer, ", ", false, true, true, true, false); string fullName = ""; if (!String.IsNullOrEmpty(sci.ProductVariant.GetLocalized(x => x.Name))) fullName = string.Format("{0} ({1})", sci.ProductVariant.Product.GetLocalized(x => x.Name), sci.ProductVariant.GetLocalized(x => x.Name)); else fullName = sci.ProductVariant.Product.GetLocalized(x => x.Name); decimal unitPrice = _taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetUnitPrice(sci, true), out taxRate); req.AddItem(fullName, description, sci.Id.ToString(), unitPrice, sci.Quantity); } } if (cart.RequiresShipping()) { //AddMerchantCalculatedShippingMethod //AddCarrierCalculatedShippingOption var shippingOptions = _shippingService.GetShippingOptions(cart, null); foreach (ShippingOption shippingOption in shippingOptions.ShippingOptions) { //adjust rate Discount appliedDiscount = null; var shippingTotal = _orderTotalCalculationService.AdjustShippingRate( shippingOption.Rate, cart, out appliedDiscount); decimal shippingRateBase = _taxService.GetShippingPrice(shippingTotal, _workContext.CurrentCustomer); req.AddFlatRateShippingMethod(shippingOption.Name, shippingRateBase); } } //add only US, GB states //CountryCollection countries = IoC.Resolve<ICountryService>().GetAllCountries(); //foreach (Country country in countries) //{ // foreach (StateProvince state in country.StateProvinces) // { // TaxByStateProvinceCollection taxByStateProvinceCollection = TaxByIoC.Resolve<IStateProvinceService>().GetAllByStateProvinceID(state.StateProvinceID); // foreach (TaxByStateProvince taxByStateProvince in taxByStateProvinceCollection) // { // if (!String.IsNullOrEmpty(state.Abbreviation)) // { // Req.AddStateTaxRule(state.Abbreviation, (double)taxByStateProvince.Percentage, false); // } // } // } //} //if (subTotalDiscountBase > decimal.Zero) //{ // req.AddItem("Discount", string.Empty, string.Empty, (decimal)(-1.0) * subTotalDiscountBase, 1); //} //foreach (AppliedGiftCard agc in appliedGiftCards) //{ // req.AddItem(string.Format("Gift Card - {0}", agc.GiftCard.GiftCardCouponCode), string.Empty, string.Empty, (decimal)(-1.0) * agc.AmountCanBeUsed, 1); //} var customerInfoDoc = new XmlDocument(); XmlElement customerInfo = customerInfoDoc.CreateElement("CustomerInfo"); customerInfo.SetAttribute("CustomerID", _workContext.CurrentCustomer.Id.ToString()); customerInfo.SetAttribute("CustomerLanguageID", _workContext.WorkingLanguage.Id.ToString()); customerInfo.SetAttribute("CustomerCurrencyID", _workContext.WorkingCurrency.Id.ToString()); req.AddMerchantPrivateDataNode(customerInfo); req.ContinueShoppingUrl = _webHelper.GetStoreLocation(false); req.EditCartUrl = _webHelper.GetStoreLocation(false) + "cart"; GCheckoutResponse resp = req.Send(); return resp; }
public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentRequest processPaymentRequest, IList <Core.Domain.Orders.OrganizedShoppingCartItem> cart) { var result = new SetExpressCheckoutResponseType(); var currentStore = CommonServices.StoreContext.CurrentStore; var req = new SetExpressCheckoutReq { SetExpressCheckoutRequest = new SetExpressCheckoutRequestType { Version = PayPalHelper.GetApiVersion(), SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType() } }; var details = new SetExpressCheckoutRequestDetailsType { PaymentAction = PayPalHelper.GetPaymentAction(Settings), PaymentActionSpecified = true, CancelURL = CommonServices.WebHelper.GetStoreLocation(currentStore.SslEnabled) + "cart", ReturnURL = CommonServices.WebHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/GetDetails", //CallbackURL = _webHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/ShippingOptions?CustomerID=" + _workContext.CurrentCustomer.Id.ToString(), //CallbackTimeout = _payPalExpressPaymentSettings.CallbackTimeout.ToString() ReqConfirmShipping = Settings.ConfirmedShipment.ToString(), NoShipping = Settings.NoShipmentAddress.ToString() }; // populate cart decimal itemTotal = decimal.Zero; var cartItems = new List <PaymentDetailsItemType>(); foreach (OrganizedShoppingCartItem item in cart) { decimal shoppingCartUnitPriceWithDiscountBase = _priceCalculationService.GetUnitPrice(item, true); decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, CommonServices.WorkContext.WorkingCurrency); decimal priceIncludingTier = shoppingCartUnitPriceWithDiscount; cartItems.Add(new PaymentDetailsItemType() { Name = item.Item.Product.Name, Number = item.Item.Product.Sku, Quantity = item.Item.Quantity.ToString(), Amount = new BasicAmountType() // this is the per item cost { currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), Value = (priceIncludingTier).ToString("N", new CultureInfo("en-us")) } }); itemTotal += (item.Item.Quantity * priceIncludingTier); } ; decimal shippingTotal = decimal.Zero; if (cart.RequiresShipping()) { decimal?shoppingCartShippingBase = OrderTotalCalculationService.GetShoppingCartShippingTotal(cart); if (shoppingCartShippingBase.HasValue && shoppingCartShippingBase > 0) { shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, CommonServices.WorkContext.WorkingCurrency); } else { shippingTotal = Settings.DefaultShippingPrice; } } //This is the default if the Shipping Callback fails //var shippingOptions = new List<ShippingOptionType>(); //shippingOptions.Add(new ShippingOptionType() //{ // ShippingOptionIsDefault = "true", // ShippingOptionName = "Standard Shipping", // ShippingOptionAmount = new BasicAmountType() // { // Value = shippingTotal.ToString(), //This is the default value used for shipping if the Instant Update API returns an error or does not answer within the callback time // currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) // } //}); //details.FlatRateShippingOptions = shippingOptions.ToArray(); //details.TotalType = TotalType.EstimatedTotal; // get total tax SortedDictionary <decimal, decimal> taxRates = null; decimal shoppingCartTaxBase = OrderTotalCalculationService.GetTaxTotal(cart, out taxRates); decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, CommonServices.WorkContext.WorkingCurrency); decimal discount = -processPaymentRequest.Discount; // Add discounts to PayPal order if (discount != 0) { cartItems.Add(new PaymentDetailsItemType() { Name = "Threadrock Discount", Quantity = "1", Amount = new BasicAmountType() // this is the total discount { currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), Value = discount.ToString("N", new CultureInfo("en-us")) } }); itemTotal += discount; } // get customer int customerId = Convert.ToInt32(CommonServices.WorkContext.CurrentCustomer.Id.ToString()); var customer = _customerService.GetCustomerById(customerId); if (!cart.IsRecurring()) { //we don't apply gift cards for recurring products var giftCards = _giftCardService.GetActiveGiftCardsAppliedByCustomer(customer); if (giftCards != null) { foreach (var gc in giftCards) { if (itemTotal > decimal.Zero) { decimal remainingAmount = gc.GetGiftCardRemainingAmount(); decimal amountCanBeUsed = decimal.Zero; if (itemTotal > remainingAmount) { amountCanBeUsed = remainingAmount; } else { amountCanBeUsed = itemTotal - .01M; } decimal amountToSubtract = -amountCanBeUsed; cartItems.Add(new PaymentDetailsItemType() { Name = "Giftcard Applied", Quantity = "1", Amount = new BasicAmountType() { currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), Value = amountToSubtract.ToString("N", new CultureInfo("en-us")) } }); //reduce subtotal itemTotal += amountToSubtract; } } } } // populate payment details var paymentDetails = new PaymentDetailsType { ItemTotal = new BasicAmountType { Value = Math.Round(itemTotal, 2).ToString("N", new CultureInfo("en-us")), currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) }, ShippingTotal = new BasicAmountType { Value = Math.Round(shippingTotal, 2).ToString("N", new CultureInfo("en-us")), currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) }, TaxTotal = new BasicAmountType { Value = Math.Round(shoppingCartTax, 2).ToString("N", new CultureInfo("en-us")), currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) }, OrderTotal = new BasicAmountType { Value = Math.Round(itemTotal + shoppingCartTax + shippingTotal, 2).ToString("N", new CultureInfo("en-us")), currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) }, Custom = processPaymentRequest.OrderGuid.ToString(), ButtonSource = SmartStoreVersion.CurrentFullVersion, PaymentAction = PayPalHelper.GetPaymentAction(Settings), PaymentDetailsItem = cartItems.ToArray() }; details.PaymentDetails = new[] { paymentDetails }; //details.MaxAmount = new BasicAmountType() // this is the per item cost //{ // currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)), // Value = (decimal.Parse(paymentDetails.OrderTotal.Value) + 30).ToString() //}; details.ShippingMethodSpecified = true; req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails.Custom = processPaymentRequest.OrderGuid.ToString(); req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails = details; using (var service = new PayPalAPIAASoapBinding()) { service.Url = PayPalHelper.GetPaypalServiceUrl(Settings); service.RequesterCredentials = PayPalHelper.GetPaypalApiCredentials(Settings); result = service.SetExpressCheckout(req); } _httpContext.GetCheckoutState().CustomProperties.Add("PayPalExpressButtonUsed", true); return(result); }
/// <summary> /// Gets a value indicating whether shipping is free /// </summary> /// <param name="cart">Cart</param> /// <returns>A value indicating whether shipping is free</returns> public virtual bool IsFreeShipping(IList <ShoppingCartItem> cart) { Customer customer = cart.GetCustomer(); if (customer != null) { //check whether customer has a free shipping if (customer.FreeShipping) { return(true); } //check whether customer is in a customer role with free shipping applied var customerRoles = customer.CustomerRoles.Where(cr => cr.Active); foreach (var customerRole in customerRoles) { if (customerRole.FreeShipping) { return(true); } } } bool shoppingCartRequiresShipping = cart.RequiresShipping(); if (!shoppingCartRequiresShipping) { return(true); } //check whether all shopping cart items are marked as free shipping bool allItemsAreFreeShipping = true; foreach (var sc in cart) { if (sc.IsShipEnabled && !sc.IsFreeShipping) { allItemsAreFreeShipping = false; break; } } if (allItemsAreFreeShipping) { return(true); } //free shipping over $X if (_shippingSettings.FreeShippingOverXEnabled) { //check whether we have subtotal enough to have free shipping decimal subTotalDiscountAmount; List <Discount> subTotalAppliedDiscounts; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; GetShoppingCartSubTotal(cart, _shippingSettings.FreeShippingOverXIncludingTax, out subTotalDiscountAmount, out subTotalAppliedDiscounts, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); if (subTotalWithDiscountBase > _shippingSettings.FreeShippingOverXValue) { return(true); } } //otherwise, return false return(false); }
protected virtual OrderTotalsModel PrepareOrderTotalsModel(IList<ShoppingCartItem> cart, bool isEditable) { var model = new OrderTotalsModel(); model.IsEditable = isEditable; if (cart.Count > 0) { //subtotal decimal orderSubTotalDiscountAmountBase; Discount orderSubTotalAppliedDiscount; decimal subTotalWithoutDiscountBase; decimal subTotalWithDiscountBase; var subTotalIncludingTax = _workContext.TaxDisplayType == TaxDisplayType.IncludingTax && !_taxSettings.ForceTaxExclusionFromOrderSubtotal; _orderTotalCalculationService.GetShoppingCartSubTotal(cart, subTotalIncludingTax, out orderSubTotalDiscountAmountBase, out orderSubTotalAppliedDiscount, out subTotalWithoutDiscountBase, out subTotalWithDiscountBase); decimal subtotalBase = subTotalWithoutDiscountBase; decimal subtotal = _currencyService.ConvertFromPrimaryStoreCurrency(subtotalBase, _workContext.WorkingCurrency); model.SubTotal = _priceFormatter.FormatPrice(subtotal, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); if (orderSubTotalDiscountAmountBase > decimal.Zero) { decimal orderSubTotalDiscountAmount = _currencyService.ConvertFromPrimaryStoreCurrency(orderSubTotalDiscountAmountBase, _workContext.WorkingCurrency); model.SubTotalDiscount = _priceFormatter.FormatPrice(-orderSubTotalDiscountAmount, true, _workContext.WorkingCurrency, _workContext.WorkingLanguage, subTotalIncludingTax); model.AllowRemovingSubTotalDiscount = orderSubTotalAppliedDiscount != null && orderSubTotalAppliedDiscount.RequiresCouponCode && !String.IsNullOrEmpty(orderSubTotalAppliedDiscount.CouponCode) && model.IsEditable; } //shipping info model.RequiresShipping = cart.RequiresShipping(); if (model.RequiresShipping) { decimal? shoppingCartShippingBase = _orderTotalCalculationService.GetShoppingCartShippingTotal(cart); if (shoppingCartShippingBase.HasValue) { decimal shoppingCartShipping = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, _workContext.WorkingCurrency); model.Shipping = _priceFormatter.FormatShippingPrice(shoppingCartShipping, true); //selected shipping method var shippingOption = _workContext.CurrentCustomer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (shippingOption != null) model.SelectedShippingMethod = shippingOption.Name; } } //payment method fee var paymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute<string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id); decimal paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethodSystemName); decimal paymentMethodAdditionalFeeWithTaxBase = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, _workContext.CurrentCustomer); if (paymentMethodAdditionalFeeWithTaxBase > decimal.Zero) { decimal paymentMethodAdditionalFeeWithTax = _currencyService.ConvertFromPrimaryStoreCurrency(paymentMethodAdditionalFeeWithTaxBase, _workContext.WorkingCurrency); model.PaymentMethodAdditionalFee = _priceFormatter.FormatPaymentMethodAdditionalFee(paymentMethodAdditionalFeeWithTax, true); } //tax bool displayTax = true; bool displayTaxRates = true; if (_taxSettings.HideTaxInOrderSummary && _workContext.TaxDisplayType == TaxDisplayType.IncludingTax) { displayTax = false; displayTaxRates = false; } else { SortedDictionary<decimal, decimal> taxRates; decimal shoppingCartTaxBase = _orderTotalCalculationService.GetTaxTotal(cart, out taxRates); decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, _workContext.WorkingCurrency); if (shoppingCartTaxBase == 0 && _taxSettings.HideZeroTax) { displayTax = false; displayTaxRates = false; } else { displayTaxRates = _taxSettings.DisplayTaxRates && taxRates.Count > 0; displayTax = !displayTaxRates; model.Tax = _priceFormatter.FormatPrice(shoppingCartTax, true, false); foreach (var tr in taxRates) { model.TaxRates.Add(new OrderTotalsModel.TaxRate { Rate = _priceFormatter.FormatTaxRate(tr.Key), Value = _priceFormatter.FormatPrice(_currencyService.ConvertFromPrimaryStoreCurrency(tr.Value, _workContext.WorkingCurrency), true, false), }); } } } model.DisplayTaxRates = displayTaxRates; model.DisplayTax = displayTax; //total decimal orderTotalDiscountAmountBase; Discount orderTotalAppliedDiscount; List<AppliedGiftCard> appliedGiftCards; int redeemedRewardPoints; decimal redeemedRewardPointsAmount; decimal? shoppingCartTotalBase = _orderTotalCalculationService.GetShoppingCartTotal(cart, out orderTotalDiscountAmountBase, out orderTotalAppliedDiscount, out appliedGiftCards, out redeemedRewardPoints, out redeemedRewardPointsAmount); if (shoppingCartTotalBase.HasValue) { decimal shoppingCartTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTotalBase.Value, _workContext.WorkingCurrency); model.OrderTotal = _priceFormatter.FormatPrice(shoppingCartTotal, true, false); } //discount if (orderTotalDiscountAmountBase > decimal.Zero) { decimal orderTotalDiscountAmount = _currencyService.ConvertFromPrimaryStoreCurrency(orderTotalDiscountAmountBase, _workContext.WorkingCurrency); model.OrderTotalDiscount = _priceFormatter.FormatPrice(-orderTotalDiscountAmount, true, false); model.AllowRemovingOrderTotalDiscount = orderTotalAppliedDiscount != null && orderTotalAppliedDiscount.RequiresCouponCode && !String.IsNullOrEmpty(orderTotalAppliedDiscount.CouponCode) && model.IsEditable; } //gift cards if (appliedGiftCards != null && appliedGiftCards.Count > 0) { foreach (var appliedGiftCard in appliedGiftCards) { var gcModel = new OrderTotalsModel.GiftCard { Id = appliedGiftCard.GiftCard.Id, CouponCode = appliedGiftCard.GiftCard.GiftCardCouponCode, }; decimal amountCanBeUsed = _currencyService.ConvertFromPrimaryStoreCurrency(appliedGiftCard.AmountCanBeUsed, _workContext.WorkingCurrency); gcModel.Amount = _priceFormatter.FormatPrice(-amountCanBeUsed, true, false); decimal remainingAmountBase = appliedGiftCard.GiftCard.GetGiftCardRemainingAmount() - appliedGiftCard.AmountCanBeUsed; decimal remainingAmount = _currencyService.ConvertFromPrimaryStoreCurrency(remainingAmountBase, _workContext.WorkingCurrency); gcModel.Remaining = _priceFormatter.FormatPrice(remainingAmount, true, false); model.GiftCards.Add(gcModel); } } //reward points to be spent (redeemed) if (redeemedRewardPointsAmount > decimal.Zero) { decimal redeemedRewardPointsAmountInCustomerCurrency = _currencyService.ConvertFromPrimaryStoreCurrency(redeemedRewardPointsAmount, _workContext.WorkingCurrency); model.RedeemedRewardPoints = redeemedRewardPoints; model.RedeemedRewardPointsAmount = _priceFormatter.FormatPrice(-redeemedRewardPointsAmountInCustomerCurrency, true, false); } //reward points to be earned if (_rewardPointsSettings.Enabled && _rewardPointsSettings.DisplayHowMuchWillBeEarned && shoppingCartTotalBase.HasValue) { model.WillEarnRewardPoints = _orderTotalCalculationService .CalculateRewardPoints(_workContext.CurrentCustomer, shoppingCartTotalBase.Value); } } return model; }
/// <summary> /// Gets a value indicating whether shipping is free /// </summary> /// <param name="cart">Cart</param> /// <returns>A value indicating whether shipping is free</returns> public virtual async Task <bool> IsFreeShipping(IList <ShoppingCartItem> cart) { Customer customer = _workContext.CurrentCustomer; if (customer != null) { //check whether customer has a free shipping if (customer.FreeShipping) { return(true); } //check whether customer is in a customer group with free shipping applied var customerGroups = await _groupService.GetAllByIds(customer.Groups.ToArray()); foreach (var customerGroup in customerGroups) { if (customerGroup.FreeShipping) { return(true); } } } bool shoppingCartRequiresShipping = cart.RequiresShipping(); if (!shoppingCartRequiresShipping) { return(true); } //check whether all shopping cart items are marked as free shipping bool allItemsAreFreeShipping = true; foreach (var sc in cart) { if (sc.IsShipEnabled && !sc.IsFreeShipping) { allItemsAreFreeShipping = false; break; } } if (allItemsAreFreeShipping) { return(true); } //free shipping over $X if (_shippingSettings.FreeShippingOverXEnabled) { //check whether we have subtotal enough to have free shipping var(discountAmount, appliedDiscounts, subTotalWithoutDiscount, subTotalWithDiscount, taxRates) = await GetShoppingCartSubTotal(cart, _shippingSettings.FreeShippingOverXIncludingTax); var subTotalDiscountAmount = discountAmount; var subTotalAppliedDiscounts = appliedDiscounts; var subTotalWithoutDiscountBase = subTotalWithoutDiscount; var subTotalWithDiscountBase = subTotalWithDiscount; if (subTotalWithDiscountBase > _shippingSettings.FreeShippingOverXValue) { return(true); } } //otherwise, return false return(false); }
protected virtual CheckoutBillingAddressModel PrepareBillingAddressModel(IList<ShoppingCartItem> cart, int? selectedCountryId = null, bool prePopulateNewAddressWithCustomerFields = false, string overrideAttributesXml = "") { var model = new CheckoutBillingAddressModel(); model.ShipToSameAddressAllowed = _shippingSettings.ShipToSameAddress && cart.RequiresShipping(); model.ShipToSameAddress = true; //existing addresses var addresses = _workContext.CurrentCustomer.Addresses .Where(a => a.Country == null || (//published a.Country.Published && //allow billing a.Country.AllowsBilling && //enabled for the current store _storeMappingService.Authorize(a.Country))) .ToList(); foreach (var address in addresses) { var addressModel = new AddressModel(); addressModel.PrepareModel( address: address, excludeProperties: false, addressSettings: _addressSettings, addressAttributeFormatter: _addressAttributeFormatter); model.ExistingAddresses.Add(addressModel); } //new address model.NewAddress.CountryId = selectedCountryId; model.NewAddress.PrepareModel(address: null, excludeProperties: false, addressSettings: _addressSettings, localizationService: _localizationService, stateProvinceService: _stateProvinceService, addressAttributeService: _addressAttributeService, addressAttributeParser: _addressAttributeParser, loadCountries: () => _countryService.GetAllCountriesForBilling(_workContext.WorkingLanguage.Id), prePopulateWithCustomerFields: prePopulateNewAddressWithCustomerFields, customer: _workContext.CurrentCustomer, overrideAttributesXml: overrideAttributesXml); return model; }
/// <summary> /// Gets a value indicating whether shipping is free /// </summary> /// <param name="cart">Cart</param> /// <param name="subTotal">Subtotal amount; pass null to calculate subtotal</param> /// <returns>A value indicating whether shipping is free</returns> public virtual bool IsFreeShipping(IList<ShoppingCartItem> cart, decimal? subTotal = null) { if (!cart.RequiresShipping()) return true; //check whether customer is in a customer role with free shipping applied var customer = cart.GetCustomer(); if (customer != null && customer.CustomerRoles.Where(role => role.Active).Any(role => role.FreeShipping)) return true; //check whether all shopping cart items are marked as free shipping if (cart.All(item => item.IsShipEnabled && item.IsFreeShipping)) return true; //free shipping over $X if (_shippingSettings.FreeShippingOverXEnabled) { if (!subTotal.HasValue) { decimal discountAmount; List<Discount> appliedDiscounts; decimal subTotalWithoutDiscount; decimal subTotalWithDiscount; GetShoppingCartSubTotal(cart, _shippingSettings.FreeShippingOverXIncludingTax, out discountAmount, out appliedDiscounts, out subTotalWithoutDiscount, out subTotalWithDiscount); subTotal = subTotalWithDiscount; } //check whether we have subtotal enough to have free shipping if (subTotal.Value > _shippingSettings.FreeShippingOverXValue) return true; } return false; }
protected void PrepareShoppingCartModel(ShoppingCartModel model, IList<OrganizedShoppingCartItem> cart, bool isEditable = true, bool validateCheckoutAttributes = false, bool prepareEstimateShippingIfEnabled = true, bool setEstimateShippingDefaultAddress = true, bool prepareAndDisplayOrderReviewData = false) { if (cart == null) throw new ArgumentNullException("cart"); if (model == null) throw new ArgumentNullException("model"); if (cart.Count == 0) return; #region Simple properties model.MediaDimensions = _mediaSettings.CartThumbPictureSize; model.BundleThumbSize = _mediaSettings.CartThumbBundleItemPictureSize; model.DisplayDeliveryTime = _shoppingCartSettings.ShowDeliveryTimes; model.DisplayShortDesc = _shoppingCartSettings.ShowShortDesc; model.DisplayBasePrice = _shoppingCartSettings.ShowBasePrice; model.DisplayWeight = _shoppingCartSettings.ShowWeight; model.IsEditable = isEditable; model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart; model.ShowProductBundleImages = _shoppingCartSettings.ShowProductBundleImagesOnShoppingCart; model.ShowSku = _catalogSettings.ShowProductSku; var checkoutAttributesXml = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService); model.CheckoutAttributeInfo = HtmlUtils.ConvertPlainTextToTable(HtmlUtils.ConvertHtmlToPlainText( _checkoutAttributeFormatter.FormatAttributes(checkoutAttributesXml, _workContext.CurrentCustomer) )); //model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(_workContext.CurrentCustomer.CheckoutAttributes, _workContext.CurrentCustomer); //model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(_workContext.CurrentCustomer.CheckoutAttributes, _workContext.CurrentCustomer, "", false); bool minOrderSubtotalAmountOk = _orderProcessingService.ValidateMinOrderSubtotalAmount(cart); if (!minOrderSubtotalAmountOk) { decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); model.MinOrderSubtotalWarning = string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false)); } model.TermsOfServiceEnabled = _orderSettings.TermsOfServiceEnabled; //gift card and gift card boxes model.DiscountBox.Display = _shoppingCartSettings.ShowDiscountBox; var discountCouponCode = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.DiscountCouponCode); var discount = _discountService.GetDiscountByCouponCode(discountCouponCode); if (discount != null && discount.RequiresCouponCode && _discountService.IsDiscountValid(discount, _workContext.CurrentCustomer)) model.DiscountBox.CurrentCode = discount.CouponCode; model.GiftCardBox.Display = _shoppingCartSettings.ShowGiftCardBox; model.DisplayCommentBox = _shoppingCartSettings.ShowCommentBox; //cart warnings var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, checkoutAttributesXml, validateCheckoutAttributes); foreach (var warning in cartWarnings) model.Warnings.Add(warning); #endregion #region Checkout attributes var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(); if (!cart.RequiresShipping()) { //remove attributes which require shippable products checkoutAttributes = checkoutAttributes.RemoveShippableAttributes(); } foreach (var attribute in checkoutAttributes) { var caModel = new ShoppingCartModel.CheckoutAttributeModel() { Id = attribute.Id, Name = attribute.GetLocalized(x => x.Name), TextPrompt = attribute.GetLocalized(x => x.TextPrompt), IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType }; if (attribute.ShouldHaveValues()) { //values var caValues = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id); foreach (var caValue in caValues) { var pvaValueModel = new ShoppingCartModel.CheckoutAttributeValueModel() { Id = caValue.Id, Name = caValue.GetLocalized(x => x.Name), IsPreSelected = caValue.IsPreSelected }; caModel.Values.Add(pvaValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(caValue); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment); } } } //set already selected attributes string selectedCheckoutAttributes = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService); switch (attribute.AttributeControlType) { case AttributeControlType.DropdownList: case AttributeControlType.RadioList: case AttributeControlType.ColorSquares: case AttributeControlType.Checkboxes: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { //clear default selection foreach (var item in caModel.Values) item.IsPreSelected = false; //select new values var selectedCaValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes); foreach (var caValue in selectedCaValues) foreach (var item in caModel.Values) if (caValue.Id == item.Id) item.IsPreSelected = true; } } break; case AttributeControlType.TextBox: case AttributeControlType.MultilineTextbox: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (enteredText.Count > 0) caModel.DefaultValue = enteredText[0]; } } break; case AttributeControlType.Datepicker: { //keep in mind my that the code below works only in the current culture var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (selectedDateStr.Count > 0) { DateTime selectedDate; if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture, DateTimeStyles.None, out selectedDate)) { //successfully parsed caModel.SelectedDay = selectedDate.Day; caModel.SelectedMonth = selectedDate.Month; caModel.SelectedYear = selectedDate.Year; } } } break; default: break; } model.CheckoutAttributes.Add(caModel); } #endregion #region Estimate shipping if (prepareEstimateShippingIfEnabled) { model.EstimateShipping.Enabled = cart.Count > 0 && cart.RequiresShipping() && _shippingSettings.EstimateShippingEnabled; if (model.EstimateShipping.Enabled) { //countries int? defaultEstimateCountryId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.CountryId : model.EstimateShipping.CountryId; //model.EstimateShipping.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Address.SelectCountry"), Value = "0" }); foreach (var c in _countryService.GetAllCountriesForShipping()) model.EstimateShipping.AvailableCountries.Add(new SelectListItem() { Text = c.GetLocalized(x => x.Name), Value = c.Id.ToString(), Selected = c.Id == defaultEstimateCountryId }); //states int? defaultEstimateStateId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.StateProvinceId : model.EstimateShipping.StateProvinceId; var states = defaultEstimateCountryId.HasValue ? _stateProvinceService.GetStateProvincesByCountryId(defaultEstimateCountryId.Value).ToList() : new List<StateProvince>(); if (states.Count > 0) foreach (var s in states) model.EstimateShipping.AvailableStates.Add(new SelectListItem() { Text = s.GetLocalized(x => x.Name), Value = s.Id.ToString(), Selected = s.Id == defaultEstimateStateId }); else model.EstimateShipping.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Address.OtherNonUS"), Value = "0" }); if (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) model.EstimateShipping.ZipPostalCode = _workContext.CurrentCustomer.ShippingAddress.ZipPostalCode; } } #endregion #region Cart items foreach (var sci in cart) { var shoppingCartItemModel = PrepareShoppingCartItemModel(sci); model.Items.Add(shoppingCartItemModel); } #endregion #region Order review data if (prepareAndDisplayOrderReviewData) { model.OrderReviewData.Display = true; //billing info var billingAddress = _workContext.CurrentCustomer.BillingAddress; if (billingAddress != null) model.OrderReviewData.BillingAddress.PrepareModel(billingAddress, false, _addressSettings); //shipping info if (cart.RequiresShipping()) { model.OrderReviewData.IsShippable = true; var shippingAddress = _workContext.CurrentCustomer.ShippingAddress; if (shippingAddress != null) model.OrderReviewData.ShippingAddress.PrepareModel(shippingAddress, false, _addressSettings); //selected shipping method var shippingOption = _workContext.CurrentCustomer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (shippingOption != null) model.OrderReviewData.ShippingMethod = shippingOption.Name; } //payment info var selectedPaymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute<string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id); var checkoutState = _httpContext.GetCheckoutState(); var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(selectedPaymentMethodSystemName); model.OrderReviewData.PaymentMethod = paymentMethod != null ? _pluginMediator.GetLocalizedFriendlyName(paymentMethod.Metadata) : ""; model.OrderReviewData.PaymentSummary = checkoutState.PaymentSummary; model.OrderReviewData.IsPaymentSelectionSkipped = checkoutState.IsPaymentSelectionSkipped; } #endregion PrepareButtonPaymentMethodModel(model.ButtonPaymentMethods, cart); }
/// <summary> /// Validates whether this shopping cart is valid /// </summary> /// <param name="shoppingCart">Shopping cart</param> /// <param name="checkoutAttributes">Checkout attributes</param> /// <param name="validateCheckoutAttributes">A value indicating whether to validate checkout attributes</param> /// <returns>Warnings</returns> public virtual IList<string> GetShoppingCartWarnings(IList<ShoppingCartItem> shoppingCart, string checkoutAttributes, bool validateCheckoutAttributes) { var warnings = new List<string>(); bool hasStandartProducts = false; bool hasRecurringProducts = false; foreach (var sci in shoppingCart) { var productVariant = sci.ProductVariant; if (productVariant == null) { warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.CannotLoadProductVariant"), sci.ProductVariantId)); return warnings; } if (productVariant.IsRecurring) hasRecurringProducts = true; else hasStandartProducts = true; } //don't mix standard and recurring products if (hasStandartProducts && hasRecurringProducts) warnings.Add(_localizationService.GetResource("ShoppingCart.CannotMixStandardAndAutoshipProducts")); //recurring cart validation if (hasRecurringProducts) { int cycleLength = 0; RecurringProductCyclePeriod cyclePeriod = RecurringProductCyclePeriod.Days; int totalCycles = 0; string cyclesError = shoppingCart.GetRecurringCycleInfo(out cycleLength, out cyclePeriod, out totalCycles); if (!string.IsNullOrEmpty(cyclesError)) { warnings.Add(cyclesError); return warnings; } } //validate checkout attributes if (validateCheckoutAttributes) { //selected attributes var ca1Collection = _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttributes); //existing checkout attributes var ca2Collection = _checkoutAttributeService.GetAllCheckoutAttributes(); if (!shoppingCart.RequiresShipping()) { //remove attributes which require shippable products ca2Collection = ca2Collection.RemoveShippableAttributes(); } foreach (var ca2 in ca2Collection) { if (ca2.IsRequired) { bool found = false; //selected checkout attributes foreach (var ca1 in ca1Collection) { if (ca1.Id == ca2.Id) { var caValuesStr = _checkoutAttributeParser.ParseValues(checkoutAttributes, ca1.Id); foreach (string str1 in caValuesStr) if (!String.IsNullOrEmpty(str1.Trim())) { found = true; break; } } } //if not found if (!found) { if (!string.IsNullOrEmpty(ca2.GetLocalized(a => a.TextPrompt))) warnings.Add(ca2.GetLocalized(a => a.TextPrompt)); else warnings.Add(string.Format(_localizationService.GetResource("ShoppingCart.SelectAttribute"), ca2.GetLocalized(a => a.Name))); } } } } return warnings; }
/// <summary> /// Update order totals /// </summary> /// <param name="updateOrderParameters">Parameters for the updating order</param> /// <param name="restoredCart">Shopping cart</param> public virtual void UpdateOrderTotals(UpdateOrderParameters updateOrderParameters, IList<ShoppingCartItem> restoredCart) { var updatedOrder = updateOrderParameters.UpdatedOrder; var updatedOrderItem = updateOrderParameters.UpdatedOrderItem; //get the customer var customer = restoredCart.GetCustomer(); #region Sub total var subTotalExclTax = decimal.Zero; var subTotalInclTax = decimal.Zero; var subTotalTaxRates = new SortedDictionary<decimal, decimal>(); foreach (var shoppingCartItem in restoredCart) { var itemSubTotalExclTax = decimal.Zero; var itemSubTotalInclTax = decimal.Zero; var taxRate = decimal.Zero; var itemDiscounts = new List<Discount>(); //calculate subtotal for the updated order item if (shoppingCartItem.Id == updatedOrderItem.Id) { //update order item updatedOrderItem.UnitPriceExclTax = updateOrderParameters.PriceExclTax; updatedOrderItem.UnitPriceInclTax = updateOrderParameters.PriceInclTax; updatedOrderItem.DiscountAmountExclTax = updateOrderParameters.DiscountAmountExclTax; updatedOrderItem.DiscountAmountInclTax = updateOrderParameters.DiscountAmountInclTax; updatedOrderItem.PriceExclTax = itemSubTotalExclTax = updateOrderParameters.SubTotalExclTax; updatedOrderItem.PriceInclTax = itemSubTotalInclTax = updateOrderParameters.SubTotalInclTax; updatedOrderItem.Quantity = shoppingCartItem.Quantity; taxRate = Math.Round((100 * (itemSubTotalInclTax - itemSubTotalExclTax)) / itemSubTotalExclTax, 3); } else { //get the already calculated subtotal from the order item itemSubTotalExclTax = updatedOrder.OrderItems.FirstOrDefault(item => item.Id == shoppingCartItem.Id).PriceExclTax; itemSubTotalInclTax = updatedOrder.OrderItems.FirstOrDefault(item => item.Id == shoppingCartItem.Id).PriceInclTax; taxRate = Math.Round((100 * (itemSubTotalInclTax - itemSubTotalExclTax)) / itemSubTotalExclTax, 3); } foreach (var discount in itemDiscounts) if (!updateOrderParameters.AppliedDiscounts.ContainsDiscount(discount)) updateOrderParameters.AppliedDiscounts.Add(discount); subTotalExclTax += itemSubTotalExclTax; subTotalInclTax += itemSubTotalInclTax; //tax rates var itemTaxValue = itemSubTotalInclTax - itemSubTotalExclTax; if (taxRate > decimal.Zero && itemTaxValue > decimal.Zero) { if (!subTotalTaxRates.ContainsKey(taxRate)) subTotalTaxRates.Add(taxRate, itemTaxValue); else subTotalTaxRates[taxRate] = subTotalTaxRates[taxRate] + itemTaxValue; } } if (subTotalExclTax < decimal.Zero) subTotalExclTax = decimal.Zero; if (subTotalInclTax < decimal.Zero) subTotalInclTax = decimal.Zero; //We calculate discount amount on order subtotal excl tax (discount first) //calculate discount amount ('Applied to order subtotal' discount) List<Discount> subTotalDiscounts; var discountAmountExclTax = GetOrderSubtotalDiscount(customer, subTotalExclTax, out subTotalDiscounts); if (subTotalExclTax < discountAmountExclTax) discountAmountExclTax = subTotalExclTax; var discountAmountInclTax = discountAmountExclTax; //add tax for shopping items var tempTaxRates = new Dictionary<decimal, decimal>(subTotalTaxRates); foreach (var kvp in tempTaxRates) { if (kvp.Value != decimal.Zero && subTotalExclTax > decimal.Zero) { var discountTaxValue = kvp.Value * (discountAmountExclTax / subTotalExclTax); discountAmountInclTax += discountTaxValue; subTotalTaxRates[kvp.Key] = kvp.Value - discountTaxValue; } } //rounding if (_shoppingCartSettings.RoundPricesDuringCalculation) { subTotalExclTax = RoundingHelper.RoundPrice(subTotalExclTax); subTotalInclTax = RoundingHelper.RoundPrice(subTotalInclTax); discountAmountExclTax = RoundingHelper.RoundPrice(discountAmountExclTax); discountAmountInclTax = RoundingHelper.RoundPrice(discountAmountInclTax); } updatedOrder.OrderSubtotalExclTax = subTotalExclTax; updatedOrder.OrderSubtotalInclTax = subTotalInclTax; updatedOrder.OrderSubTotalDiscountExclTax = discountAmountExclTax; updatedOrder.OrderSubTotalDiscountInclTax = discountAmountInclTax; foreach (var discount in subTotalDiscounts) if (!updateOrderParameters.AppliedDiscounts.ContainsDiscount(discount)) updateOrderParameters.AppliedDiscounts.Add(discount); #endregion #region Shipping var shippingTotalExclTax = decimal.Zero; var shippingTotalInclTax = decimal.Zero; var shippingTaxRate = decimal.Zero; if (restoredCart.RequiresShipping()) { if (!IsFreeShipping(restoredCart, _shippingSettings.FreeShippingOverXIncludingTax ? subTotalInclTax : subTotalExclTax)) { var shippingTotal = decimal.Zero; if (!string.IsNullOrEmpty(updatedOrder.ShippingRateComputationMethodSystemName)) { //in the updated order were shipping items if (updatedOrder.PickUpInStore) { //customer chose pickup in store method, try to get chosen pickup point if (_shippingSettings.AllowPickUpInStore) { var pickupPointsResponse = _shippingService.GetPickupPoints(updatedOrder.BillingAddress, updatedOrder.ShippingRateComputationMethodSystemName, _storeContext.CurrentStore.Id); if (pickupPointsResponse.Success) { var selectedPickupPoint = pickupPointsResponse.PickupPoints.FirstOrDefault(point => updatedOrder.ShippingMethod.Contains(point.Name)); if (selectedPickupPoint != null) shippingTotal = selectedPickupPoint.PickupFee; else updateOrderParameters.Warnings.Add(string.Format("Shipping method {0} could not be loaded", updatedOrder.ShippingMethod)); } else updateOrderParameters.Warnings.AddRange(pickupPointsResponse.Errors); } else updateOrderParameters.Warnings.Add("Pick up in store is not available"); } else { //customer chose shipping to address, try to get chosen shipping option var shippingOptionsResponse = _shippingService.GetShippingOptions(restoredCart, updatedOrder.ShippingAddress, updatedOrder.ShippingRateComputationMethodSystemName, _storeContext.CurrentStore.Id); if (shippingOptionsResponse.Success) { var shippingOption = shippingOptionsResponse.ShippingOptions.FirstOrDefault(option => updatedOrder.ShippingMethod.Contains(option.Name)); if (shippingOption != null) shippingTotal = shippingOption.Rate; else updateOrderParameters.Warnings.Add(string.Format("Shipping method {0} could not be loaded", updatedOrder.ShippingMethod)); } else updateOrderParameters.Warnings.AddRange(shippingOptionsResponse.Errors); } } else { //before updating order was without shipping if (_shippingSettings.AllowPickUpInStore) { //try to get the cheapest pickup point var pickupPointsResponse = _shippingService.GetPickupPoints(updatedOrder.BillingAddress, null, _storeContext.CurrentStore.Id); if (pickupPointsResponse.Success) { updateOrderParameters.PickupPoint = pickupPointsResponse.PickupPoints.OrderBy(point => point.PickupFee).First(); shippingTotal = updateOrderParameters.PickupPoint.PickupFee; } else updateOrderParameters.Warnings.AddRange(pickupPointsResponse.Errors); } else updateOrderParameters.Warnings.Add("Pick up in store is not available"); if (updateOrderParameters.PickupPoint == null) { //or try to get the cheapest shipping option for the shipping to the customer address var shippingRateComputationMethods = _shippingService.LoadActiveShippingRateComputationMethods(_storeContext.CurrentStore.Id); if (shippingRateComputationMethods.Any()) { var shippingOptionsResponse = _shippingService.GetShippingOptions(restoredCart, customer.ShippingAddress, null, _storeContext.CurrentStore.Id); if (shippingOptionsResponse.Success) { var shippingOption = shippingOptionsResponse.ShippingOptions.OrderBy(option => option.Rate).First(); updatedOrder.ShippingRateComputationMethodSystemName = shippingOption.ShippingRateComputationMethodSystemName; updatedOrder.ShippingMethod = shippingOption.Name; updatedOrder.ShippingAddress = (Address)customer.ShippingAddress.Clone(); shippingTotal = shippingOption.Rate; } else updateOrderParameters.Warnings.AddRange(shippingOptionsResponse.Errors); } else updateOrderParameters.Warnings.Add("Shipping rate computation method could not be loaded"); } } //additional shipping charge shippingTotal += restoredCart.Where(item => item.IsShipEnabled && !item.IsFreeShipping).Sum(item => item.Product.AdditionalShippingCharge); //shipping discounts List<Discount> shippingTotalDiscounts; shippingTotal -= GetShippingDiscount(customer, shippingTotal, out shippingTotalDiscounts); if (shippingTotal < decimal.Zero) shippingTotal = decimal.Zero; shippingTotalExclTax = _taxService.GetShippingPrice(shippingTotal, false, customer); shippingTotalInclTax = _taxService.GetShippingPrice(shippingTotal, true, customer, out shippingTaxRate); //rounding if (_shoppingCartSettings.RoundPricesDuringCalculation) { shippingTotalExclTax = RoundingHelper.RoundPrice(shippingTotalExclTax); shippingTotalInclTax = RoundingHelper.RoundPrice(shippingTotalInclTax); } //change shipping status if (updatedOrder.ShippingStatus == ShippingStatus.ShippingNotRequired || updatedOrder.ShippingStatus == ShippingStatus.NotYetShipped) updatedOrder.ShippingStatus = ShippingStatus.NotYetShipped; else updatedOrder.ShippingStatus = ShippingStatus.PartiallyShipped; foreach (var discount in shippingTotalDiscounts) if (!updateOrderParameters.AppliedDiscounts.ContainsDiscount(discount)) updateOrderParameters.AppliedDiscounts.Add(discount); } } else updatedOrder.ShippingStatus = ShippingStatus.ShippingNotRequired; updatedOrder.OrderShippingExclTax = shippingTotalExclTax; updatedOrder.OrderShippingInclTax = shippingTotalInclTax; #endregion #region Tax rates var taxRates = new SortedDictionary<decimal, decimal>(); //order subtotal taxes var subTotalTax = decimal.Zero; foreach (var kvp in subTotalTaxRates) { subTotalTax += kvp.Value; if (kvp.Key > decimal.Zero && kvp.Value > decimal.Zero) { if (!taxRates.ContainsKey(kvp.Key)) taxRates.Add(kvp.Key, kvp.Value); else taxRates[kvp.Key] = taxRates[kvp.Key] + kvp.Value; } } //shipping taxes var shippingTax = decimal.Zero; if (_taxSettings.ShippingIsTaxable) { shippingTax = shippingTotalInclTax - shippingTotalExclTax; if (shippingTax < decimal.Zero) shippingTax = decimal.Zero; if (shippingTaxRate > decimal.Zero && shippingTax > decimal.Zero) { if (!taxRates.ContainsKey(shippingTaxRate)) taxRates.Add(shippingTaxRate, shippingTax); else taxRates[shippingTaxRate] = taxRates[shippingTaxRate] + shippingTax; } } //payment method additional fee tax var paymentMethodAdditionalFeeTax = decimal.Zero; if (_taxSettings.PaymentMethodAdditionalFeeIsTaxable) { paymentMethodAdditionalFeeTax = updatedOrder.PaymentMethodAdditionalFeeInclTax - updatedOrder.PaymentMethodAdditionalFeeExclTax; if (paymentMethodAdditionalFeeTax < decimal.Zero) paymentMethodAdditionalFeeTax = decimal.Zero; if (updatedOrder.PaymentMethodAdditionalFeeExclTax > decimal.Zero) { var paymentTaxRate = Math.Round(100 * paymentMethodAdditionalFeeTax / updatedOrder.PaymentMethodAdditionalFeeExclTax, 3); if (paymentTaxRate > decimal.Zero && paymentMethodAdditionalFeeTax > decimal.Zero) { if (!taxRates.ContainsKey(paymentTaxRate)) taxRates.Add(paymentTaxRate, paymentMethodAdditionalFeeTax); else taxRates[paymentTaxRate] = taxRates[paymentTaxRate] + paymentMethodAdditionalFeeTax; } } } //add at least one tax rate (0%) if (!taxRates.Any()) taxRates.Add(decimal.Zero, decimal.Zero); //summarize taxes var taxTotal = subTotalTax + shippingTax + paymentMethodAdditionalFeeTax; if (taxTotal < decimal.Zero) taxTotal = decimal.Zero; //round tax if (_shoppingCartSettings.RoundPricesDuringCalculation) taxTotal = RoundingHelper.RoundPrice(taxTotal); updatedOrder.OrderTax = taxTotal; updatedOrder.TaxRates = taxRates.Aggregate(string.Empty, (current, next) => string.Format("{0}{1}:{2}; ", current, next.Key.ToString(CultureInfo.InvariantCulture), next.Value.ToString(CultureInfo.InvariantCulture))); #endregion #region Total var total = (subTotalExclTax - discountAmountExclTax) + shippingTotalExclTax + updatedOrder.PaymentMethodAdditionalFeeExclTax + taxTotal; //get discounts for the order total List<Discount> orderAppliedDiscounts; var discountAmountTotal = GetOrderTotalDiscount(customer, total, out orderAppliedDiscounts); if (total < discountAmountTotal) discountAmountTotal = total; total -= discountAmountTotal; //applied giftcards foreach (var giftCard in _giftCardService.GetAllGiftCards(usedWithOrderId: updatedOrder.Id)) { if (total > decimal.Zero) { var remainingAmount = giftCard.GiftCardUsageHistory.Where(history => history.UsedWithOrderId == updatedOrder.Id).Sum(history => history.UsedValue); var amountCanBeUsed = total > remainingAmount ? remainingAmount : total; total -= amountCanBeUsed; } } //reward points var rewardPointsOfOrder = _rewardPointService.GetRewardPointsHistory(customer.Id, true).FirstOrDefault(history => history.UsedWithOrder == updatedOrder); if (rewardPointsOfOrder != null) { var rewardPoints = -rewardPointsOfOrder.Points; var rewardPointsAmount = ConvertRewardPointsToAmount(rewardPoints); if (total < rewardPointsAmount) { rewardPoints = ConvertAmountToRewardPoints(total); rewardPointsAmount = total; } if (total > decimal.Zero) total -= rewardPointsAmount; //uncomment here for the return unused reward points if new order total less redeemed reward points amount //if (rewardPoints < -rewardPointsOfOrder.Points) // _rewardPointService.AddRewardPointsHistoryEntry(customer, -rewardPointsOfOrder.Points - rewardPoints, _storeContext.CurrentStore.Id, "Return unused reward points"); if (rewardPointsAmount != rewardPointsOfOrder.UsedAmount) { rewardPointsOfOrder.UsedAmount = rewardPointsAmount; rewardPointsOfOrder.Points = -rewardPoints; _rewardPointService.UpdateRewardPointsHistoryEntry(rewardPointsOfOrder); } } //rounding if (total < decimal.Zero) total = decimal.Zero; if (_shoppingCartSettings.RoundPricesDuringCalculation) total = RoundingHelper.RoundPrice(total); updatedOrder.OrderDiscount = discountAmountTotal; updatedOrder.OrderTotal = total; foreach (var discount in orderAppliedDiscounts) if (!updateOrderParameters.AppliedDiscounts.ContainsDiscount(discount)) updateOrderParameters.AppliedDiscounts.Add(discount); #endregion }
/// <summary> /// Gets a value indicating whether shipping is free /// </summary> /// <param name="cart">Cart</param> /// <returns>A value indicating whether shipping is free</returns> public virtual bool IsFreeShipping(IList<ShoppingCartItem> cart) { Customer customer = cart.GetCustomer(); if (customer != null) { //check whether customer is in a customer role with free shipping applied var customerRoles = customer.CustomerRoles.Where(cr => cr.Active); foreach (var customerRole in customerRoles) if (customerRole.FreeShipping) return true; } bool shoppingCartRequiresShipping = cart.RequiresShipping(); if (!shoppingCartRequiresShipping) return true; //check whether all shopping cart items are marked as free shipping bool allItemsAreFreeShipping = true; foreach (var sc in cart) { if (sc.IsShipEnabled && !sc.IsFreeShipping) { allItemsAreFreeShipping = false; break; } } if (allItemsAreFreeShipping) return true; //otherwise, return false return false; }
protected virtual void PrepareShoppingCartModel(ShoppingCartModel model, IList<ShoppingCartItem> cart, bool isEditable = true, bool validateCheckoutAttributes = false, bool prepareEstimateShippingIfEnabled = true, bool setEstimateShippingDefaultAddress = true, bool prepareAndDisplayOrderReviewData = false) { if (cart == null) throw new ArgumentNullException("cart"); if (model == null) throw new ArgumentNullException("model"); if (cart.Count == 0) return; #region Simple properties model.IsEditable = isEditable; model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart; model.ShowSku = _catalogSettings.ShowProductSku; var checkoutAttributesXml = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id); model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(checkoutAttributesXml, _workContext.CurrentCustomer); bool minOrderSubtotalAmountOk = _orderProcessingService.ValidateMinOrderSubtotalAmount(cart); if (!minOrderSubtotalAmountOk) { decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); model.MinOrderSubtotalWarning = string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false)); } model.TermsOfServiceOnShoppingCartPage = _orderSettings.TermsOfServiceOnShoppingCartPage; model.TermsOfServiceOnOrderConfirmPage = _orderSettings.TermsOfServiceOnOrderConfirmPage; model.OnePageCheckoutEnabled = _orderSettings.OnePageCheckoutEnabled; //gift card and gift card boxes model.DiscountBox.Display= _shoppingCartSettings.ShowDiscountBox; var discountCouponCode = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.DiscountCouponCode); var discount = _discountService.GetDiscountByCouponCode(discountCouponCode); if (discount != null && discount.RequiresCouponCode && _discountService.IsDiscountValid(discount, _workContext.CurrentCustomer)) model.DiscountBox.CurrentCode = discount.CouponCode; model.GiftCardBox.Display = _shoppingCartSettings.ShowGiftCardBox; //cart warnings var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, checkoutAttributesXml, validateCheckoutAttributes); foreach (var warning in cartWarnings) model.Warnings.Add(warning); #endregion #region Checkout attributes var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(_storeContext.CurrentStore.Id, !cart.RequiresShipping()); foreach (var attribute in checkoutAttributes) { var caModel = new ShoppingCartModel.CheckoutAttributeModel() { Id = attribute.Id, Name = attribute.GetLocalized(x => x.Name), TextPrompt = attribute.GetLocalized(x => x.TextPrompt), IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType, DefaultValue = attribute.DefaultValue }; if (!String.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions)) { caModel.AllowedFileExtensions = attribute.ValidationFileAllowedExtensions .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .ToList(); } if (attribute.ShouldHaveValues()) { //values var caValues = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id); foreach (var caValue in caValues) { var pvaValueModel = new ShoppingCartModel.CheckoutAttributeValueModel() { Id = caValue.Id, Name = caValue.GetLocalized(x => x.Name), ColorSquaresRgb = caValue.ColorSquaresRgb, IsPreSelected = caValue.IsPreSelected, }; caModel.Values.Add(pvaValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(caValue); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment); } } } //set already selected attributes string selectedCheckoutAttributes = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id); switch (attribute.AttributeControlType) { case AttributeControlType.DropdownList: case AttributeControlType.RadioList: case AttributeControlType.Checkboxes: case AttributeControlType.ColorSquares: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { //clear default selection foreach (var item in caModel.Values) item.IsPreSelected = false; //select new values var selectedCaValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes); foreach (var caValue in selectedCaValues) foreach (var item in caModel.Values) if (caValue.Id == item.Id) item.IsPreSelected = true; } } break; case AttributeControlType.ReadonlyCheckboxes: { //do nothing //values are already pre-set } break; case AttributeControlType.TextBox: case AttributeControlType.MultilineTextbox: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (enteredText.Count > 0) caModel.DefaultValue = enteredText[0]; } } break; case AttributeControlType.Datepicker: { //keep in mind my that the code below works only in the current culture var selectedDateStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (selectedDateStr.Count > 0) { DateTime selectedDate; if (DateTime.TryParseExact(selectedDateStr[0], "D", CultureInfo.CurrentCulture, DateTimeStyles.None, out selectedDate)) { //successfully parsed caModel.SelectedDay = selectedDate.Day; caModel.SelectedMonth = selectedDate.Month; caModel.SelectedYear = selectedDate.Year; } } } break; default: break; } model.CheckoutAttributes.Add(caModel); } #endregion #region Estimate shipping if (prepareEstimateShippingIfEnabled) { model.EstimateShipping.Enabled = cart.Count > 0 && cart.RequiresShipping() && _shippingSettings.EstimateShippingEnabled; if (model.EstimateShipping.Enabled) { //countries int? defaultEstimateCountryId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.CountryId : model.EstimateShipping.CountryId; model.EstimateShipping.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Address.SelectCountry"), Value = "0" }); foreach (var c in _countryService.GetAllCountriesForShipping()) model.EstimateShipping.AvailableCountries.Add(new SelectListItem() { Text = c.GetLocalized(x => x.Name), Value = c.Id.ToString(), Selected = c.Id == defaultEstimateCountryId }); //states int? defaultEstimateStateId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.StateProvinceId : model.EstimateShipping.StateProvinceId; var states = defaultEstimateCountryId.HasValue ? _stateProvinceService.GetStateProvincesByCountryId(defaultEstimateCountryId.Value).ToList() : new List<StateProvince>(); if (states.Count > 0) foreach (var s in states) model.EstimateShipping.AvailableStates.Add(new SelectListItem() { Text = s.GetLocalized(x => x.Name), Value = s.Id.ToString(), Selected = s.Id == defaultEstimateStateId }); else model.EstimateShipping.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Address.OtherNonUS"), Value = "0" }); if (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) model.EstimateShipping.ZipPostalCode = _workContext.CurrentCustomer.ShippingAddress.ZipPostalCode; } } #endregion #region Cart items foreach (var sci in cart) { var cartItemModel = new ShoppingCartModel.ShoppingCartItemModel() { Id = sci.Id, Sku = sci.Product.FormatSku(sci.AttributesXml, _productAttributeParser), ProductId = sci.Product.Id, ProductName = sci.Product.GetLocalized(x => x.Name), ProductSeName = sci.Product.GetSeName(), Quantity = sci.Quantity, AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.Product, sci.AttributesXml), }; //allow editing? //1. setting enabled? //2. simple product? //3. has attribute or gift card? //4. visible individually? cartItemModel.AllowItemEditing = _shoppingCartSettings.AllowCartItemEditing && sci.Product.ProductType == ProductType.SimpleProduct && (!String.IsNullOrEmpty(cartItemModel.AttributeInfo) || sci.Product.IsGiftCard) && sci.Product.VisibleIndividually; //allowed quantities var allowedQuantities = sci.Product.ParseAllowedQuatities(); foreach (var qty in allowedQuantities) { cartItemModel.AllowedQuantities.Add(new SelectListItem() { Text = qty.ToString(), Value = qty.ToString(), Selected = sci.Quantity == qty }); } //recurring info if (sci.Product.IsRecurring) cartItemModel.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"), sci.Product.RecurringCycleLength, sci.Product.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext)); //unit prices if (sci.Product.CallForPrice) { cartItemModel.UnitPrice = _localizationService.GetResource("Products.CallForPrice"); } else { decimal taxRate = decimal.Zero; decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetUnitPrice(sci, true), out taxRate); decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency); cartItemModel.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount); } //subtotal, discount if (sci.Product.CallForPrice) { cartItemModel.SubTotal = _localizationService.GetResource("Products.CallForPrice"); } else { //sub total decimal taxRate = decimal.Zero; decimal shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, true), out taxRate); decimal shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency); cartItemModel.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount); //display an applied discount amount decimal shoppingCartItemSubTotalWithoutDiscountBase = _taxService.GetProductPrice(sci.Product, _priceCalculationService.GetSubTotal(sci, false), out taxRate); decimal shoppingCartItemDiscountBase = shoppingCartItemSubTotalWithoutDiscountBase - shoppingCartItemSubTotalWithDiscountBase; if (shoppingCartItemDiscountBase > decimal.Zero) { decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency); cartItemModel.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount); } } //picture if (_shoppingCartSettings.ShowProductImagesOnShoppingCart) { cartItemModel.Picture = PrepareCartItemPictureModel(sci, _mediaSettings.CartThumbPictureSize, true, cartItemModel.ProductName); } //item warnings var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings( _workContext.CurrentCustomer, sci.ShoppingCartType, sci.Product, sci.StoreId, sci.AttributesXml, sci.CustomerEnteredPrice, sci.Quantity, false); foreach (var warning in itemWarnings) cartItemModel.Warnings.Add(warning); model.Items.Add(cartItemModel); } #endregion #region Button payment methods var boundPaymentMethods = _paymentService .LoadActivePaymentMethods(_workContext.CurrentCustomer.Id, _storeContext.CurrentStore.Id) .Where(pm => pm.PaymentMethodType == PaymentMethodType.Button) .ToList(); foreach (var pm in boundPaymentMethods) { if (cart.IsRecurring() && pm.RecurringPaymentType == RecurringPaymentType.NotSupported) continue; string actionName; string controllerName; RouteValueDictionary routeValues; pm.GetPaymentInfoRoute(out actionName, out controllerName, out routeValues); model.ButtonPaymentMethodActionNames.Add(actionName); model.ButtonPaymentMethodControllerNames.Add(controllerName); model.ButtonPaymentMethodRouteValues.Add(routeValues); } #endregion #region Order review data if (prepareAndDisplayOrderReviewData) { model.OrderReviewData.Display = true; //billing info var billingAddress = _workContext.CurrentCustomer.BillingAddress; if (billingAddress != null) model.OrderReviewData.BillingAddress.PrepareModel(billingAddress, false, _addressSettings); //shipping info if (cart.RequiresShipping()) { model.OrderReviewData.IsShippable = true; if (_shippingSettings.AllowPickUpInStore) { model.OrderReviewData.SelectedPickUpInStore = _workContext.CurrentCustomer.GetAttribute<bool>(SystemCustomerAttributeNames.SelectedPickUpInStore, _storeContext.CurrentStore.Id); } if (!model.OrderReviewData.SelectedPickUpInStore) { var shippingAddress = _workContext.CurrentCustomer.ShippingAddress; if (shippingAddress != null) { model.OrderReviewData.ShippingAddress.PrepareModel(shippingAddress, false, _addressSettings); } } //selected shipping method var shippingOption = _workContext.CurrentCustomer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (shippingOption != null) model.OrderReviewData.ShippingMethod = shippingOption.Name; } //payment info var selectedPaymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute<string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _storeContext.CurrentStore.Id); var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(selectedPaymentMethodSystemName); model.OrderReviewData.PaymentMethod = paymentMethod != null ? paymentMethod.GetLocalizedFriendlyName(_localizationService, _workContext.WorkingLanguage.Id) : ""; } #endregion }
/// <summary> /// Post cart to google /// </summary> /// <param name="req">Pre-generated request</param> /// <param name="cart">Shopping cart</param> /// <returns>Response</returns> public GCheckoutResponse PostCartToGoogle(CheckoutShoppingCartRequest req, IList <Core.Domain.Orders.ShoppingCartItem> cart) { //there's no need to round prices (Math.Round(,2)) because GCheckout library does it for us //items foreach (Core.Domain.Orders.ShoppingCartItem sci in cart) { var productVariant = sci.ProductVariant; if (productVariant != null) { decimal taxRate = decimal.Zero; string description = _productAttributeFormatter.FormatAttributes(productVariant, sci.AttributesXml, _workContext.CurrentCustomer, ", ", false); string fullName = ""; if (!String.IsNullOrEmpty(sci.ProductVariant.GetLocalized(x => x.Name))) { fullName = string.Format("{0} ({1})", sci.ProductVariant.Product.GetLocalized(x => x.Name), sci.ProductVariant.GetLocalized(x => x.Name)); } else { fullName = sci.ProductVariant.Product.GetLocalized(x => x.Name); } decimal unitPrice = _taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetUnitPrice(sci, true), out taxRate); req.AddItem(fullName, description, sci.Id.ToString(), unitPrice, sci.Quantity); } } if (cart.RequiresShipping()) { //AddMerchantCalculatedShippingMethod //AddCarrierCalculatedShippingOption var shippingOptions = _shippingService.GetShippingOptions(cart, null); foreach (ShippingOption shippingOption in shippingOptions.ShippingOptions) { req.AddFlatRateShippingMethod(shippingOption.Name, _taxService.GetShippingPrice(shippingOption.Rate, _workContext.CurrentCustomer)); } } //add only US, GB states //CountryCollection countries = IoC.Resolve<ICountryService>().GetAllCountries(); //foreach (Country country in countries) //{ // foreach (StateProvince state in country.StateProvinces) // { // TaxByStateProvinceCollection taxByStateProvinceCollection = TaxByIoC.Resolve<IStateProvinceService>().GetAllByStateProvinceID(state.StateProvinceID); // foreach (TaxByStateProvince taxByStateProvince in taxByStateProvinceCollection) // { // if (!String.IsNullOrEmpty(state.Abbreviation)) // { // Req.AddStateTaxRule(state.Abbreviation, (double)taxByStateProvince.Percentage, false); // } // } // } //} //if (subTotalDiscountBase > decimal.Zero) //{ // req.AddItem("Discount", string.Empty, string.Empty, (decimal)(-1.0) * subTotalDiscountBase, 1); //} //foreach (AppliedGiftCard agc in appliedGiftCards) //{ // req.AddItem(string.Format("Gift Card - {0}", agc.GiftCard.GiftCardCouponCode), string.Empty, string.Empty, (decimal)(-1.0) * agc.AmountCanBeUsed, 1); //} var customerInfoDoc = new XmlDocument(); XmlElement customerInfo = customerInfoDoc.CreateElement("CustomerInfo"); customerInfo.SetAttribute("CustomerID", _workContext.CurrentCustomer.Id.ToString()); customerInfo.SetAttribute("CustomerLanguageID", _workContext.WorkingLanguage.Id.ToString()); customerInfo.SetAttribute("CustomerCurrencyID", _workContext.WorkingCurrency.Id.ToString()); req.AddMerchantPrivateDataNode(customerInfo); req.ContinueShoppingUrl = _webHelper.GetStoreLocation(false); req.EditCartUrl = _webHelper.GetStoreLocation(false) + "cart"; GCheckoutResponse resp = req.Send(); return(resp); }
public virtual async Task <IList <string> > GetShoppingCartWarnings(IList <ShoppingCartItem> shoppingCart, IList <CustomAttribute> checkoutAttributes, bool validateCheckoutAttributes) { var warnings = new List <string>(); if (checkoutAttributes == null) { checkoutAttributes = new List <CustomAttribute>(); } bool hasStandartProducts = false; bool hasRecurringProducts = false; foreach (var sci in shoppingCart) { var product = await _productService.GetProductById(sci.ProductId); if (product == null) { warnings.Add(string.Format(_translationService.GetResource("ShoppingCart.CannotLoadProduct"), sci.ProductId)); return(warnings); } if (product.IsRecurring) { hasRecurringProducts = true; } else { hasStandartProducts = true; } } //don't mix standard and recurring products if (hasStandartProducts && hasRecurringProducts) { warnings.Add(_translationService.GetResource("ShoppingCart.CannotMixStandardAndAutoshipProducts")); } //validate checkout attributes if (validateCheckoutAttributes) { //selected attributes var attributes1 = await _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttributes); //existing checkout attributes var attributes2 = await _checkoutAttributeService.GetAllCheckoutAttributes(_workContext.CurrentStore.Id, !shoppingCart.RequiresShipping()); foreach (var a2 in attributes2) { var conditionMet = await _checkoutAttributeParser.IsConditionMet(a2, checkoutAttributes); if (a2.IsRequired && ((conditionMet.HasValue && conditionMet.Value) || !conditionMet.HasValue)) { bool found = false; //selected checkout attributes foreach (var a1 in attributes1) { if (a1.Id == a2.Id) { var attributeValuesStr = checkoutAttributes.Where(x => x.Key == a1.Id).Select(x => x.Value); foreach (var str1 in attributeValuesStr) { if (!string.IsNullOrEmpty(str1.Trim())) { found = true; break; } } } } //if not found if (!found) { if (!string.IsNullOrEmpty(a2.GetTranslation(a => a.TextPrompt, _workContext.WorkingLanguage.Id))) { warnings.Add(a2.GetTranslation(a => a.TextPrompt, _workContext.WorkingLanguage.Id)); } else { warnings.Add(string.Format(_translationService.GetResource("ShoppingCart.SelectAttribute"), a2.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id))); } } } } //now validation rules //minimum length foreach (var ca in attributes2) { if (ca.ValidationMinLength.HasValue) { if (ca.AttributeControlTypeId == AttributeControlType.TextBox || ca.AttributeControlTypeId == AttributeControlType.MultilineTextbox) { var valuesStr = checkoutAttributes.Where(x => x.Key == ca.Id).Select(x => x.Value); var enteredText = valuesStr?.FirstOrDefault(); int enteredTextLength = string.IsNullOrEmpty(enteredText) ? 0 : enteredText.Length; if (ca.ValidationMinLength.Value > enteredTextLength) { warnings.Add(string.Format(_translationService.GetResource("ShoppingCart.TextboxMinimumLength"), ca.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id), ca.ValidationMinLength.Value)); } } } //maximum length if (ca.ValidationMaxLength.HasValue) { if (ca.AttributeControlTypeId == AttributeControlType.TextBox || ca.AttributeControlTypeId == AttributeControlType.MultilineTextbox) { var valuesStr = checkoutAttributes.Where(x => x.Key == ca.Id).Select(x => x.Value); var enteredText = valuesStr?.FirstOrDefault(); int enteredTextLength = string.IsNullOrEmpty(enteredText) ? 0 : enteredText.Length; if (ca.ValidationMaxLength.Value < enteredTextLength) { warnings.Add(string.Format(_translationService.GetResource("ShoppingCart.TextboxMaximumLength"), ca.GetTranslation(a => a.Name, _workContext.WorkingLanguage.Id), ca.ValidationMaxLength.Value)); } } } } } //event notification await _mediator.ShoppingCartWarningsAdd(warnings, shoppingCart, checkoutAttributes, validateCheckoutAttributes); return(warnings); }
public SetExpressCheckoutResponseType SetExpressCheckout(PayPalProcessPaymentRequest processPaymentRequest, IList <OrganizedShoppingCartItem> cart) { var result = new SetExpressCheckoutResponseType(); var store = Services.StoreService.GetStoreById(processPaymentRequest.StoreId); var customer = Services.WorkContext.CurrentCustomer; var settings = Services.Settings.LoadSetting <PayPalExpressPaymentSettings>(processPaymentRequest.StoreId); var payPalCurrency = GetApiCurrency(store.PrimaryStoreCurrency); var excludingTax = (Services.WorkContext.GetTaxDisplayTypeFor(customer, store.Id) == TaxDisplayType.ExcludingTax); var req = new SetExpressCheckoutReq { SetExpressCheckoutRequest = new SetExpressCheckoutRequestType { Version = ApiVersion, SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType() } }; var details = new SetExpressCheckoutRequestDetailsType { PaymentAction = GetPaymentAction(settings), PaymentActionSpecified = true, CancelURL = Services.WebHelper.GetStoreLocation(store.SslEnabled) + "cart", ReturnURL = Services.WebHelper.GetStoreLocation(store.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/GetDetails", //CallbackURL = _webHelper.GetStoreLocation(currentStore.SslEnabled) + "Plugins/SmartStore.PayPal/PayPalExpress/ShippingOptions?CustomerID=" + _workContext.CurrentCustomer.Id.ToString(), //CallbackTimeout = _payPalExpressPaymentSettings.CallbackTimeout.ToString() ReqConfirmShipping = settings.ConfirmedShipment.ToString(), NoShipping = settings.NoShipmentAddress.ToString() }; // populate cart var taxRate = decimal.Zero; var unitPriceTaxRate = decimal.Zero; var itemTotal = decimal.Zero; var cartItems = new List <PaymentDetailsItemType>(); foreach (var item in cart) { var product = item.Item.Product; var unitPrice = _priceCalculationService.GetUnitPrice(item, true); var shoppingCartUnitPriceWithDiscount = excludingTax ? _taxService.GetProductPrice(product, unitPrice, false, customer, out taxRate) : _taxService.GetProductPrice(product, unitPrice, true, customer, out unitPriceTaxRate); cartItems.Add(new PaymentDetailsItemType { Name = product.Name, Number = product.Sku, Quantity = item.Item.Quantity.ToString(), // this is the per item cost Amount = new BasicAmountType { currencyID = payPalCurrency, Value = shoppingCartUnitPriceWithDiscount.FormatInvariant() } }); itemTotal += (item.Item.Quantity * shoppingCartUnitPriceWithDiscount); } ; // additional handling fee var additionalHandlingFee = GetAdditionalHandlingFee(cart); cartItems.Add(new PaymentDetailsItemType { Name = T("Plugins.Payments.PayPal.PaymentMethodFee").Text, Quantity = "1", Amount = new BasicAmountType() { currencyID = payPalCurrency, Value = additionalHandlingFee.FormatInvariant() } }); itemTotal += GetAdditionalHandlingFee(cart); //shipping var shippingTotal = decimal.Zero; if (cart.RequiresShipping()) { decimal?shoppingCartShippingBase = OrderTotalCalculationService.GetShoppingCartShippingTotal(cart); if (shoppingCartShippingBase.HasValue && shoppingCartShippingBase > 0) { shippingTotal = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartShippingBase.Value, Services.WorkContext.WorkingCurrency); } else { shippingTotal = settings.DefaultShippingPrice; } } //This is the default if the Shipping Callback fails //var shippingOptions = new List<ShippingOptionType>(); //shippingOptions.Add(new ShippingOptionType() //{ // ShippingOptionIsDefault = "true", // ShippingOptionName = "Standard Shipping", // ShippingOptionAmount = new BasicAmountType() // { // Value = shippingTotal.ToString(), //This is the default value used for shipping if the Instant Update API returns an error or does not answer within the callback time // currencyID = PaypalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) // } //}); //details.FlatRateShippingOptions = shippingOptions.ToArray(); //details.TotalType = TotalType.EstimatedTotal; // get total tax //SortedDictionary<decimal, decimal> taxRates = null; //decimal shoppingCartTaxBase = OrderTotalCalculationService.GetTaxTotal(cart, out taxRates); //decimal shoppingCartTax = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartTaxBase, CommonServices.WorkContext.WorkingCurrency); // discount var discount = -processPaymentRequest.Discount; if (discount != 0) { cartItems.Add(new PaymentDetailsItemType { Name = T("Plugins.Payments.PayPal.ThreadrockDiscount").Text, Quantity = "1", Amount = new BasicAmountType // this is the total discount { currencyID = payPalCurrency, Value = discount.FormatInvariant() } }); itemTotal += discount; } if (!cart.IsRecurring()) { //we don't apply gift cards for recurring products var giftCards = _giftCardService.GetActiveGiftCardsAppliedByCustomer(customer, Services.StoreContext.CurrentStore.Id); if (giftCards != null) { foreach (var gc in giftCards) { if (itemTotal > decimal.Zero) { decimal remainingAmount = gc.GetGiftCardRemainingAmount(); decimal amountCanBeUsed = decimal.Zero; if (itemTotal > remainingAmount) { amountCanBeUsed = remainingAmount; } else { amountCanBeUsed = itemTotal - .01M; } decimal amountToSubtract = -amountCanBeUsed; cartItems.Add(new PaymentDetailsItemType { Name = T("Plugins.Payments.PayPal.GiftcardApplied").Text, Quantity = "1", Amount = new BasicAmountType { currencyID = payPalCurrency, Value = amountToSubtract.FormatInvariant() } }); //reduce subtotal itemTotal += amountToSubtract; } } } } // populate payment details var paymentDetails = new PaymentDetailsType { ItemTotal = new BasicAmountType { Value = Math.Round(itemTotal, 2).FormatInvariant(), currencyID = payPalCurrency }, ShippingTotal = new BasicAmountType { Value = Math.Round(shippingTotal, 2).FormatInvariant(), currencyID = payPalCurrency }, //TaxTotal = new BasicAmountType //{ // Value = Math.Round(shoppingCartTax, 2).ToString("N", new CultureInfo("en-us")), // currencyID = PayPalHelper.GetPaypalCurrency(_currencyService.GetCurrencyById(_currencySettings.PrimaryStoreCurrencyId)) //}, OrderTotal = new BasicAmountType { Value = Math.Round(itemTotal + shippingTotal, 2).FormatInvariant(), currencyID = payPalCurrency }, Custom = processPaymentRequest.OrderGuid.ToString(), ButtonSource = SmartStoreVersion.CurrentFullVersion, PaymentAction = GetPaymentAction(settings), PaymentDetailsItem = cartItems.ToArray() }; details.PaymentDetails = new[] { paymentDetails }; details.ShippingMethodSpecified = true; req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails.Custom = processPaymentRequest.OrderGuid.ToString(); req.SetExpressCheckoutRequest.SetExpressCheckoutRequestDetails = details; using (var service = GetApiAaService(settings)) { result = service.SetExpressCheckout(req); } var checkoutState = _httpContext.GetCheckoutState(); if (checkoutState.CustomProperties.ContainsKey("PayPalExpressButtonUsed")) { checkoutState.CustomProperties["PayPalExpressButtonUsed"] = true; } else { checkoutState.CustomProperties.Add("PayPalExpressButtonUsed", true); } return(result); }
protected CheckoutPaymentMethodModel PreparePaymentMethodModel(IList <OrganizedShoppingCartItem> cart) { var model = new CheckoutPaymentMethodModel(); // was shipping skipped var shippingOptions = _shippingService.GetShippingOptions(cart, _workContext.CurrentCustomer.ShippingAddress, "", _storeContext.CurrentStore.Id).ShippingOptions; if (!cart.RequiresShipping() || (shippingOptions.Count <= 1 && _shippingSettings.SkipShippingIfSingleOption)) { model.SkippedSelectShipping = true; } var paymentTypes = new PaymentMethodType[] { PaymentMethodType.Standard, PaymentMethodType.Redirection, PaymentMethodType.StandardAndRedirection }; var boundPaymentMethods = _paymentService .LoadActivePaymentMethods(_workContext.CurrentCustomer, cart, _storeContext.CurrentStore.Id, paymentTypes) .ToList(); var allPaymentMethods = _paymentService.GetAllPaymentMethods(); foreach (var pm in boundPaymentMethods) { if (cart.IsRecurring() && pm.Value.RecurringPaymentType == RecurringPaymentType.NotSupported) { continue; } var paymentMethod = allPaymentMethods.FirstOrDefault(x => x.PaymentMethodSystemName.IsCaseInsensitiveEqual(pm.Metadata.SystemName)); var pmModel = new CheckoutPaymentMethodModel.PaymentMethodModel { Name = _pluginMediator.GetLocalizedFriendlyName(pm.Metadata), Description = _pluginMediator.GetLocalizedDescription(pm.Metadata), PaymentMethodSystemName = pm.Metadata.SystemName, PaymentInfoRoute = pm.Value.GetPaymentInfoRoute(), RequiresInteraction = pm.Value.RequiresInteraction }; if (paymentMethod != null) { pmModel.FullDescription = paymentMethod.GetLocalized(x => x.FullDescription, _workContext.WorkingLanguage.Id); } pmModel.BrandUrl = _pluginMediator.GetBrandImageUrl(pm.Metadata); // payment method additional fee decimal paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, pm.Metadata.SystemName); decimal rateBase = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, _workContext.CurrentCustomer); decimal rate = _currencyService.ConvertFromPrimaryStoreCurrency(rateBase, _workContext.WorkingCurrency); if (rate != decimal.Zero) { pmModel.Fee = _priceFormatter.FormatPaymentMethodAdditionalFee(rate, true); } model.PaymentMethods.Add(pmModel); } // find a selected (previously) payment method var selectedPaymentMethodSystemName = _workContext.CurrentCustomer.GetAttribute <string>( SystemCustomerAttributeNames.SelectedPaymentMethod, _genericAttributeService, _storeContext.CurrentStore.Id); bool selected = false; if (selectedPaymentMethodSystemName.HasValue()) { var paymentMethodToSelect = model.PaymentMethods.Find(pm => pm.PaymentMethodSystemName.IsCaseInsensitiveEqual(selectedPaymentMethodSystemName)); if (paymentMethodToSelect != null) { paymentMethodToSelect.Selected = true; selected = true; } } // if no option has been selected, let's do it for the first one if (!selected) { var paymentMethodToSelect = model.PaymentMethods.FirstOrDefault(); if (paymentMethodToSelect != null) { paymentMethodToSelect.Selected = true; } } return(model); }
protected ShoppingCartModel PrepareShoppingCartModel(ShoppingCartModel model, IList<ShoppingCartItem> cart, bool isEditable, bool setEstimateShippingDefaultAddress = true) { if (cart == null) throw new ArgumentNullException("cart"); if (model == null) throw new ArgumentNullException("model"); if (cart.Count == 0) return model; #region Simple properties model.IsEditable = isEditable; model.ShowProductImages = _shoppingCartSettings.ShowProductImagesOnShoppingCart; model.ShowSku = _catalogSettings.ShowProductSku; model.CheckoutAttributeInfo = _checkoutAttributeFormatter.FormatAttributes(_workContext.CurrentCustomer.CheckoutAttributes, _workContext.CurrentCustomer); bool minOrderSubtotalAmountOk = _orderProcessingService.ValidateMinOrderSubtotalAmount(cart); if (!minOrderSubtotalAmountOk) { decimal minOrderSubtotalAmount = _currencyService.ConvertFromPrimaryStoreCurrency(_orderSettings.MinOrderSubtotalAmount, _workContext.WorkingCurrency); model.MinOrderSubtotalWarning = string.Format(_localizationService.GetResource("Checkout.MinOrderSubtotalAmount"), _priceFormatter.FormatPrice(minOrderSubtotalAmount, true, false)); } model.TermsOfServiceEnabled = _orderSettings.TermsOfServiceEnabled; //gift card and gift card boxes model.ShowDiscountBox = _shoppingCartSettings.ShowDiscountBox; var currentDiscountWithCode = _discountService.GetDiscountByCouponCode(_workContext.CurrentCustomer.DiscountCouponCode); model.CurrentDiscountCode = currentDiscountWithCode != null && currentDiscountWithCode.RequiresCouponCode ? currentDiscountWithCode.CouponCode : null; model.ShowGiftCardBox = _shoppingCartSettings.ShowGiftCardBox; //cart warnings var cartWarnings = _shoppingCartService.GetShoppingCartWarnings(cart, "", false); foreach (var warning in cartWarnings) model.Warnings.Add(warning); #endregion #region Checkout attributes var checkoutAttributes = _checkoutAttributeService.GetAllCheckoutAttributes(!cart.RequiresShipping()); foreach (var attribute in checkoutAttributes) { var caModel = new ShoppingCartModel.CheckoutAttributeModel() { Id = attribute.Id, Name = attribute.GetLocalized(x => x.Name), TextPrompt = attribute.TextPrompt, IsRequired = attribute.IsRequired, AttributeControlType = attribute.AttributeControlType }; if (attribute.ShouldHaveValues()) { //values var caValues = _checkoutAttributeService.GetCheckoutAttributeValues(attribute.Id); foreach (var caValue in caValues) { var pvaValueModel = new ShoppingCartModel.CheckoutAttributeValueModel() { Id = caValue.Id, Name = caValue.GetLocalized(x => x.Name), IsPreSelected = caValue.IsPreSelected }; caModel.Values.Add(pvaValueModel); //display price if allowed if (_permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal priceAdjustmentBase = _taxService.GetCheckoutAttributePrice(caValue); decimal priceAdjustment = _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, _workContext.WorkingCurrency); if (priceAdjustmentBase > decimal.Zero) pvaValueModel.PriceAdjustment = "+" + _priceFormatter.FormatPrice(priceAdjustment); else if (priceAdjustmentBase < decimal.Zero) pvaValueModel.PriceAdjustment = "-" + _priceFormatter.FormatPrice(-priceAdjustment); } } } //set already selected attributes string selectedCheckoutAttributes = _workContext.CurrentCustomer.CheckoutAttributes; switch (attribute.AttributeControlType) { case AttributeControlType.DropdownList: case AttributeControlType.RadioList: case AttributeControlType.Checkboxes: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { //clear default selection foreach (var item in caModel.Values) item.IsPreSelected = false; //select new values var selectedCaValues = _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes); foreach (var caValue in selectedCaValues) foreach (var item in caModel.Values) if (caValue.Id == item.Id) item.IsPreSelected = true; } } break; case AttributeControlType.TextBox: case AttributeControlType.MultilineTextbox: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { var enteredText = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id); if (enteredText.Count > 0) caModel.DefaultValue = enteredText[0]; } } break; default: break; } model.CheckoutAttributes.Add(caModel); } #endregion #region Estimate shipping model.EstimateShipping.Enabled = cart.Count > 0 && cart.RequiresShipping() && _shippingSettings.EstimateShippingEnabled; if (model.EstimateShipping.Enabled) { //countries int? defaultEstimateCountryId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.CountryId : model.EstimateShipping.CountryId; model.EstimateShipping.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Address.SelectCountry"), Value = "0" }); foreach (var c in _countryService.GetAllCountries()) model.EstimateShipping.AvailableCountries.Add(new SelectListItem() { Text = c.GetLocalized(x => x.Name), Value = c.Id.ToString(), Selected = c.Id == defaultEstimateCountryId }); //states int? defaultEstimateStateId = (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) ? _workContext.CurrentCustomer.ShippingAddress.StateProvinceId : model.EstimateShipping.StateProvinceId; var states = defaultEstimateCountryId.HasValue ? _stateProvinceService.GetStateProvincesByCountryId(defaultEstimateCountryId.Value).ToList() : new List<StateProvince>(); if (states.Count > 0) foreach (var s in states) model.EstimateShipping.AvailableStates.Add(new SelectListItem() { Text = s.GetLocalized(x => x.Name), Value = s.Id.ToString(), Selected = s.Id == defaultEstimateStateId }); else model.EstimateShipping.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Address.OtherNonUS"), Value = "0" }); if (setEstimateShippingDefaultAddress && _workContext.CurrentCustomer.ShippingAddress != null) model.EstimateShipping.ZipPostalCode = _workContext.CurrentCustomer.ShippingAddress.ZipPostalCode; } #endregion #region Cart items foreach (var sci in cart) { var cartItemModel = new ShoppingCartModel.ShoppingCartItemModel() { Id = sci.Id, Sku = sci.ProductVariant.Sku, ProductId = sci.ProductVariant.ProductId, ProductSeName = sci.ProductVariant.Product.GetSeName(), Quantity = sci.Quantity, AttributeInfo = _productAttributeFormatter.FormatAttributes(sci.ProductVariant, sci.AttributesXml), }; //recurring info if (sci.ProductVariant.IsRecurring) cartItemModel.RecurringInfo = string.Format(_localizationService.GetResource("ShoppingCart.RecurringPeriod"), sci.ProductVariant.RecurringCycleLength, sci.ProductVariant.RecurringCyclePeriod.GetLocalizedEnum(_localizationService, _workContext)); //unit prices if (sci.ProductVariant.CallForPrice) { cartItemModel.UnitPrice = _localizationService.GetResource("Products.CallForPrice"); } else { decimal taxRate = decimal.Zero; decimal shoppingCartUnitPriceWithDiscountBase = _taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetUnitPrice(sci, true), out taxRate); decimal shoppingCartUnitPriceWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartUnitPriceWithDiscountBase, _workContext.WorkingCurrency); cartItemModel.UnitPrice = _priceFormatter.FormatPrice(shoppingCartUnitPriceWithDiscount); } //subtotal, discount if (sci.ProductVariant.CallForPrice) { cartItemModel.SubTotal = _localizationService.GetResource("Products.CallForPrice"); } else { //sub total decimal taxRate = decimal.Zero; decimal shoppingCartItemSubTotalWithDiscountBase = _taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetSubTotal(sci, true), out taxRate); decimal shoppingCartItemSubTotalWithDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemSubTotalWithDiscountBase, _workContext.WorkingCurrency); cartItemModel.SubTotal = _priceFormatter.FormatPrice(shoppingCartItemSubTotalWithDiscount); //display an applied discount amount decimal shoppingCartItemSubTotalWithoutDiscountBase = _taxService.GetProductPrice(sci.ProductVariant, _priceCalculationService.GetSubTotal(sci, false), out taxRate); decimal shoppingCartItemDiscountBase = shoppingCartItemSubTotalWithoutDiscountBase - shoppingCartItemSubTotalWithDiscountBase; if (shoppingCartItemDiscountBase > decimal.Zero) { decimal shoppingCartItemDiscount = _currencyService.ConvertFromPrimaryStoreCurrency(shoppingCartItemDiscountBase, _workContext.WorkingCurrency); cartItemModel.Discount = _priceFormatter.FormatPrice(shoppingCartItemDiscount); } } //product name if (!String.IsNullOrEmpty(sci.ProductVariant.GetLocalized(x=>x.Name))) cartItemModel.ProductName = string.Format("{0} ({1})",sci.ProductVariant.Product.GetLocalized(x=>x.Name), sci.ProductVariant.GetLocalized(x=>x.Name)); else cartItemModel.ProductName = sci.ProductVariant.Product.GetLocalized(x=>x.Name); //picture if (_shoppingCartSettings.ShowProductImagesOnShoppingCart) { var picture = _pictureService.GetPictureById(sci.ProductVariant.PictureId); if (picture == null) { picture = _pictureService.GetPicturesByProductId(sci.ProductVariant.Product.Id, 1).FirstOrDefault(); } cartItemModel.Picture = new PictureModel() { ImageUrl = _pictureService.GetPictureUrl(picture, _mediaSetting.CartThumbPictureSize, true), Title = string.Format(_localizationService.GetResource("Media.Product.ImageLinkTitleFormat"), cartItemModel.ProductName), AlternateText = string.Format(_localizationService.GetResource("Media.Product.ImageAlternateTextFormat"), cartItemModel.ProductName), }; } //item warnings var itemWarnings = _shoppingCartService.GetShoppingCartItemWarnings( _workContext.CurrentCustomer, sci.ShoppingCartType, sci.ProductVariant, sci.AttributesXml, sci.CustomerEnteredPrice, sci.Quantity, false); foreach (var warning in itemWarnings) cartItemModel.Warnings.Add(warning); model.Items.Add(cartItemModel); } #endregion #region Button payment methods var boundPaymentMethods = _paymentService .LoadActivePaymentMethods(_workContext.CurrentCustomer.Id) .Where(pm => pm.PaymentMethodType == PaymentMethodType.Button) .ToList(); foreach (var pm in boundPaymentMethods) { if (cart.IsRecurring() && pm.RecurringPaymentType == RecurringPaymentType.NotSupported) continue; string actionName; string controllerName; RouteValueDictionary routeValues; pm.GetPaymentInfoRoute(out actionName, out controllerName, out routeValues); model.ButtonPaymentMethodActionNames.Add(actionName); model.ButtonPaymentMethodControllerNames.Add(controllerName); model.ButtonPaymentMethodRouteValues.Add(routeValues); } #endregion return model; }