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 }
private async Task PrepareCheckoutAttributes(ShoppingCartModel model, GetShoppingCart request) { #region Checkout attributes var checkoutAttributes = await _checkoutAttributeService.GetAllCheckoutAttributes(request.Store.Id, !request.Cart.RequiresShipping()); foreach (var attribute in checkoutAttributes) { var attributeModel = new ShoppingCartModel.CheckoutAttributeModel { Id = attribute.Id, Name = attribute.GetLocalized(x => x.Name, request.Language.Id), TextPrompt = attribute.GetLocalized(x => x.TextPrompt, request.Language.Id), 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 = attribute.CheckoutAttributeValues; foreach (var attributeValue in attributeValues) { var attributeValueModel = new ShoppingCartModel.CheckoutAttributeValueModel { Id = attributeValue.Id, Name = attributeValue.GetLocalized(x => x.Name, request.Language.Id), ColorSquaresRgb = attributeValue.ColorSquaresRgb, IsPreSelected = attributeValue.IsPreSelected, }; attributeModel.Values.Add(attributeValueModel); //display price if allowed if (await _permissionService.Authorize(StandardPermissionProvider.DisplayPrices)) { decimal priceAdjustmentBase = (await _taxService.GetCheckoutAttributePrice(attribute, attributeValue)).checkoutPrice; decimal priceAdjustment = await _currencyService.ConvertFromPrimaryStoreCurrency(priceAdjustmentBase, request.Currency); 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 = request.Customer.GetAttributeFromEntity <string>(SystemCustomerAttributeNames.CheckoutAttributes, request.Store.Id); switch (attribute.AttributeControlType) { case AttributeControlType.DropdownList: case AttributeControlType.RadioList: case AttributeControlType.Checkboxes: case AttributeControlType.ColorSquares: case AttributeControlType.ImageSquares: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { //clear default selection foreach (var item in attributeModel.Values) { item.IsPreSelected = false; } //select new values var selectedValues = await _checkoutAttributeParser.ParseCheckoutAttributeValues(selectedCheckoutAttributes); foreach (var attributeValue in selectedValues) { if (attributeModel.Id == attributeValue.CheckoutAttributeId) { 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.Any()) { 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.Any()) { 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; case AttributeControlType.FileUpload: { if (!String.IsNullOrEmpty(selectedCheckoutAttributes)) { var downloadGuidStr = _checkoutAttributeParser.ParseValues(selectedCheckoutAttributes, attribute.Id).FirstOrDefault(); Guid downloadGuid; Guid.TryParse(downloadGuidStr, out downloadGuid); var download = await _downloadService.GetDownloadByGuid(downloadGuid); if (download != null) { attributeModel.DefaultValue = download.DownloadGuid.ToString(); } } } break; default: break; } model.CheckoutAttributes.Add(attributeModel); } #endregion }
public override async Task MapAsync(IEnumerable <OrganizedShoppingCartItem> from, ShoppingCartModel to, dynamic parameters = null) { Guard.NotNull(from, nameof(from)); Guard.NotNull(to, nameof(to)); if (!from.Any()) { return; } await base.MapAsync(from, to, null); var store = _services.StoreContext.CurrentStore; var customer = _services.WorkContext.CurrentCustomer; var currency = _services.WorkContext.WorkingCurrency; var isEditable = parameters?.IsEditable == true; var validateCheckoutAttributes = parameters?.ValidateCheckoutAttributes == true; var prepareEstimateShippingIfEnabled = parameters?.PrepareEstimateShippingIfEnabled == true; var setEstimateShippingDefaultAddress = parameters?.SetEstimateShippingDefaultAddress == true; var prepareAndDisplayOrderReviewData = parameters?.PrepareAndDisplayOrderReviewData == true; #region Simple properties to.MediaDimensions = _mediaSettings.CartThumbPictureSize; to.DeliveryTimesPresentation = _shoppingCartSettings.DeliveryTimesInShoppingCart; to.DisplayBasePrice = _shoppingCartSettings.ShowBasePrice; to.DisplayWeight = _shoppingCartSettings.ShowWeight; to.DisplayMoveToWishlistButton = await _services.Permissions.AuthorizeAsync(Permissions.Cart.AccessWishlist); to.TermsOfServiceEnabled = _orderSettings.TermsOfServiceEnabled; to.DisplayCommentBox = _shoppingCartSettings.ShowCommentBox; to.DisplayEsdRevocationWaiverBox = _shoppingCartSettings.ShowEsdRevocationWaiverBox; to.IsEditable = isEditable; var measure = await _db.MeasureWeights.FindByIdAsync(_measureSettings.BaseWeightId, false); if (measure != null) { to.MeasureUnitName = measure.GetLocalized(x => x.Name); } to.CheckoutAttributeInfo = HtmlUtils.ConvertPlainTextToTable( HtmlUtils.ConvertHtmlToPlainText( await _checkoutAttributeFormatter.FormatAttributesAsync(customer.GenericAttributes.CheckoutAttributes, customer))); // Gift card and gift card boxes. to.DiscountBox.Display = _shoppingCartSettings.ShowDiscountBox; var discountCouponCode = customer.GenericAttributes.DiscountCouponCode; var discount = await _db.Discounts .AsNoTracking() .Where(x => x.CouponCode == discountCouponCode) .FirstOrDefaultAsync(); if (discount != null && discount.RequiresCouponCode && await _discountService.IsDiscountValidAsync(discount, customer)) { to.DiscountBox.CurrentCode = discount.CouponCode; } to.GiftCardBox.Display = _shoppingCartSettings.ShowGiftCardBox; // Reward points. if (_rewardPointsSettings.Enabled && !from.IncludesMatchingItems(x => x.IsRecurring) && !customer.IsGuest()) { var rewardPointsBalance = customer.GetRewardPointsBalance(); var rewardPointsAmountBase = _orderCalculationService.ConvertRewardPointsToAmount(rewardPointsBalance); var rewardPointsAmount = _currencyService.ConvertFromPrimaryCurrency(rewardPointsAmountBase.Amount, currency); if (rewardPointsAmount > decimal.Zero) { to.RewardPoints.DisplayRewardPoints = true; to.RewardPoints.RewardPointsAmount = rewardPointsAmount.ToString(true); to.RewardPoints.RewardPointsBalance = rewardPointsBalance; to.RewardPoints.UseRewardPoints = customer.GenericAttributes.UseRewardPointsDuringCheckout; } } // Cart warnings. var warnings = new List <string>(); var cartIsValid = await _shoppingCartValidator.ValidateCartItemsAsync(from, warnings, validateCheckoutAttributes, customer.GenericAttributes.CheckoutAttributes); if (!cartIsValid) { to.Warnings.AddRange(warnings); } #endregion #region Checkout attributes var checkoutAttributes = await _checkoutAttributeMaterializer.GetValidCheckoutAttributesAsync(from); 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.IsListTypeAttribute) { var taxFormat = _currencyService.GetTaxFormat(null, null, PricingTarget.Product); var caValues = await _db.CheckoutAttributeValues .AsNoTracking() .Where(x => x.CheckoutAttributeId == attribute.Id) .ToListAsync(); // Prepare each attribute with image and price foreach (var caValue in caValues) { var pvaValueModel = new ShoppingCartModel.CheckoutAttributeValueModel { Id = caValue.Id, Name = caValue.GetLocalized(x => x.Name), IsPreSelected = caValue.IsPreSelected, Color = caValue.Color }; if (caValue.MediaFileId.HasValue && caValue.MediaFile != null) { pvaValueModel.ImageUrl = _mediaService.GetUrl(caValue.MediaFile, _mediaSettings.VariantValueThumbPictureSize, null, false); } caModel.Values.Add(pvaValueModel); // Display price if allowed. if (await _services.Permissions.AuthorizeAsync(Permissions.Catalog.DisplayPrice)) { var priceAdjustmentBase = await _taxCalculator.CalculateCheckoutAttributeTaxAsync(caValue); var priceAdjustment = _currencyService.ConvertFromPrimaryCurrency(priceAdjustmentBase.Price, currency); if (priceAdjustment > 0) { pvaValueModel.PriceAdjustment = "+" + priceAdjustment.WithPostFormat(taxFormat).ToString(); } else if (priceAdjustment < 0) { pvaValueModel.PriceAdjustment = "-" + (priceAdjustment * -1).WithPostFormat(taxFormat).ToString(); } } } } // Set already selected attributes. var selectedCheckoutAttributes = customer.GenericAttributes.CheckoutAttributes; switch (attribute.AttributeControlType) { case AttributeControlType.DropdownList: case AttributeControlType.RadioList: case AttributeControlType.Boxes: case AttributeControlType.Checkboxes: if (selectedCheckoutAttributes.AttributesMap.Any()) { // Clear default selection. foreach (var item in caModel.Values) { item.IsPreSelected = false; } // Select new values. var selectedCaValues = await _checkoutAttributeMaterializer.MaterializeCheckoutAttributeValuesAsync(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 (selectedCheckoutAttributes.AttributesMap.Any()) { var enteredText = selectedCheckoutAttributes.GetAttributeValues(attribute.Id)? .Select(x => x.ToString()) .FirstOrDefault(); if (enteredText.HasValue()) { caModel.TextValue = enteredText; } } break; case AttributeControlType.Datepicker: { // Keep in mind my that the code below works only in the current culture. var enteredDate = selectedCheckoutAttributes.AttributesMap .Where(x => x.Key == attribute.Id) .SelectMany(x => x.Value) .FirstOrDefault() .ToString(); if (enteredDate.HasValue() && DateTime.TryParseExact(enteredDate, "D", CultureInfo.CurrentCulture, DateTimeStyles.None, out var selectedDate)) { caModel.SelectedDay = selectedDate.Day; caModel.SelectedMonth = selectedDate.Month; caModel.SelectedYear = selectedDate.Year; } } break; case AttributeControlType.FileUpload: if (selectedCheckoutAttributes.AttributesMap.Any()) { var FileValue = selectedCheckoutAttributes.AttributesMap .Where(x => x.Key == attribute.Id) .Select(x => x.Value.ToString()) .FirstOrDefault(); if (FileValue.HasValue() && caModel.UploadedFileGuid.HasValue() && Guid.TryParse(caModel.UploadedFileGuid, out var guid)) { var download = await _db.Downloads .Include(x => x.MediaFile) .FirstOrDefaultAsync(x => x.DownloadGuid == guid); if (download != null && !download.UseDownloadUrl && download.MediaFile != null) { caModel.UploadedFileName = download.MediaFile.Name; } } } break; default: break; } to.CheckoutAttributes.Add(caModel); } #endregion #region Estimate shipping if (prepareEstimateShippingIfEnabled) { to.EstimateShipping.Enabled = _shippingSettings.EstimateShippingEnabled && from.Any() && from.IncludesMatchingItems(x => x.IsShippingEnabled); if (to.EstimateShipping.Enabled) { // Countries. var defaultEstimateCountryId = setEstimateShippingDefaultAddress && customer.ShippingAddress != null ? customer.ShippingAddress.CountryId : to.EstimateShipping.CountryId; var countriesForShipping = await _db.Countries .AsNoTracking() .ApplyStoreFilter(store.Id) .Where(x => x.AllowsShipping) .ToListAsync(); foreach (var countries in countriesForShipping) { to.EstimateShipping.AvailableCountries.Add(new SelectListItem { Text = countries.GetLocalized(x => x.Name), Value = countries.Id.ToString(), Selected = countries.Id == defaultEstimateCountryId }); } // States. var states = defaultEstimateCountryId.HasValue ? await _db.StateProvinces.AsNoTracking().ApplyCountryFilter(defaultEstimateCountryId.Value).ToListAsync() : new(); if (states.Any()) { var defaultEstimateStateId = setEstimateShippingDefaultAddress && customer.ShippingAddress != null ? customer.ShippingAddress.StateProvinceId : to.EstimateShipping.StateProvinceId; foreach (var s in states) { to.EstimateShipping.AvailableStates.Add(new SelectListItem { Text = s.GetLocalized(x => x.Name), Value = s.Id.ToString(), Selected = s.Id == defaultEstimateStateId }); } } else { to.EstimateShipping.AvailableStates.Add(new SelectListItem { Text = T("Address.OtherNonUS"), Value = "0" }); } if (setEstimateShippingDefaultAddress && customer.ShippingAddress != null) { to.EstimateShipping.ZipPostalCode = customer.ShippingAddress.ZipPostalCode; } } } #endregion #region Cart items var allProducts = from .Select(x => x.Item.Product) .Union(from.Select(x => x.ChildItems).SelectMany(child => child.Select(x => x.Item.Product))) .ToArray(); var batchContext = _productService.CreateProductBatchContext(allProducts, null, customer, false); var subtotal = await _orderCalculationService.GetShoppingCartSubtotalAsync(from.ToList(), null, batchContext); dynamic itemParameters = new ExpandoObject(); itemParameters.TaxFormat = _currencyService.GetTaxFormat(); itemParameters.BatchContext = batchContext; itemParameters.CartSubtotal = subtotal; foreach (var cartItem in from) { var model = new ShoppingCartModel.ShoppingCartItemModel(); await cartItem.MapAsync(model, (object)itemParameters); to.AddItems(model); } #endregion #region Order review data if (prepareAndDisplayOrderReviewData) { var checkoutState = _httpContextAccessor.HttpContext?.GetCheckoutState(); to.OrderReviewData.Display = true; // Billing info. var billingAddress = customer.BillingAddress; if (billingAddress != null) { await MapperFactory.MapAsync(billingAddress, to.OrderReviewData.BillingAddress); } // Shipping info. if (from.IsShippingRequired()) { to.OrderReviewData.IsShippable = true; var shippingAddress = customer.ShippingAddress; if (shippingAddress != null) { await MapperFactory.MapAsync(shippingAddress, to.OrderReviewData.ShippingAddress); } // Selected shipping method. var shippingOption = customer.GenericAttributes.SelectedShippingOption; if (shippingOption != null) { to.OrderReviewData.ShippingMethod = shippingOption.Name; } if (checkoutState != null && checkoutState.CustomProperties.ContainsKey("HasOnlyOneActiveShippingMethod")) { to.OrderReviewData.DisplayShippingMethodChangeOption = !(bool)checkoutState.CustomProperties.Get("HasOnlyOneActiveShippingMethod"); } } if (checkoutState != null && checkoutState.CustomProperties.ContainsKey("HasOnlyOneActivePaymentMethod")) { to.OrderReviewData.DisplayPaymentMethodChangeOption = !(bool)checkoutState.CustomProperties.Get("HasOnlyOneActivePaymentMethod"); } var selectedPaymentMethodSystemName = customer.GenericAttributes.SelectedPaymentMethod; var paymentMethod = await _paymentService.LoadPaymentMethodBySystemNameAsync(selectedPaymentMethodSystemName); // TODO: (ms) (core) Wait for PluginMediator.GetLocalizedFriendlyName implementation //model.OrderReviewData.PaymentMethod = paymentMethod != null ? _pluginMediator.GetLocalizedFriendlyName(paymentMethod.Metadata) : ""; to.OrderReviewData.PaymentSummary = checkoutState.PaymentSummary; to.OrderReviewData.IsPaymentSelectionSkipped = checkoutState.IsPaymentSelectionSkipped; } #endregion var paymentTypes = new PaymentMethodType[] { PaymentMethodType.Button, PaymentMethodType.StandardAndButton }; var boundPaymentMethods = await _paymentService.LoadActivePaymentMethodsAsync( customer, from.ToList(), store.Id, paymentTypes, false); var bpmModel = new ButtonPaymentMethodModel(); foreach (var boundPaymentMethod in boundPaymentMethods) { if (from.IncludesMatchingItems(x => x.IsRecurring) && boundPaymentMethod.Value.RecurringPaymentType == RecurringPaymentType.NotSupported) { continue; } var widgetInvoker = boundPaymentMethod.Value.GetPaymentInfoWidget(); bpmModel.Items.Add(widgetInvoker); } to.ButtonPaymentMethods = bpmModel; }