/// <summary> /// Return a new basket request. The basket will have two lines in it, for three items. Set required and common basket attributes in the header too. /// </summary> /// <param name="companyKey">The company key which indicates to Promo which company to create the product within. /// Company keys are visible in the Administration Portal, within Company Management under Configuration</param> /// <returns>A new BasketRequest.</returns> public static BasketRequest GetBasketRequest(string companyKey, bool getMissedPromotions) { BasketRequest basketRequest = new BasketRequest() { // Required attributes CompanyKey = companyKey, SaleDateTime = DateTime.UtcNow, Id = Guid.NewGuid().ToString(), // Each basket must have a unique ID (though where a basket is submitted multiple times it should maintain the same ID). // Indicate whether we want to get missed promotions GetMissedPromotions = getMissedPromotions, // Additional basket attributes DeliveryPrice = 10.99M, DeliveryMethod = "NEXTDAY", CustomerGroup = "NORMAL", Channel = "RETAIL", StoreGroup = "LONDON", Store = "KINGSTON" }; // We can add basket level custom attributes if needed basketRequest.AddCustomAttribute("testbasket", "true"); // We must have one or mote items in the basket. A basket item can have a quantity greater than one if required. BasketRequestItem basketRequestItem1 = new BasketRequestItem() { // We must always have a line number, price and quantity, and then a ProductCode and optionally a VariantCode. Id = 1, Price = 27.56M, Quantity = 2, ProductCode = "PR-25", // This is the 'adidas Consortium Campus 80s Running Shoes' from the sample product set. }; basketRequest.AddItem(basketRequestItem1); BasketRequestItem basketRequestItem2 = new BasketRequestItem() { Id = 2, Price = 15.00M, Quantity = 1, ProductCode = "PR-29" // This is the 'Custom T-Shirt' from the sample product set. }; // We can also add custom attributes against an item in the basket if needed basketRequestItem1.AddCustomAttribute("message", "This is my t-shirt!"); basketRequest.AddItem(basketRequestItem2); return(basketRequest); }
public static BasketRequest ToQixolPromosBasketRequest(this IList<ShoppingCartItem> cart) { IProductService _productService = EngineContext.Current.Resolve<IProductService>(); IPriceCalculationService _priceCalculationService = EngineContext.Current.Resolve<IPriceCalculationService>(); IWorkContext _workContext = EngineContext.Current.Resolve<IWorkContext>(); IStoreContext _storeContext = EngineContext.Current.Resolve<IStoreContext>(); IGenericAttributeService _genericAttributeService = EngineContext.Current.Resolve<IGenericAttributeService>(); PromoSettings _promoSettings = EngineContext.Current.Resolve<PromoSettings>(); IPromoUtilities _promoUtilities = EngineContext.Current.Resolve<IPromoUtilities>(); IOrderTotalCalculationService _orderTotalCalculationService = EngineContext.Current.Resolve<IOrderTotalCalculationService>(); ICurrencyService _currencyService = EngineContext.Current.Resolve<ICurrencyService>(); IShoppingCartService _shoppingCartService = EngineContext.Current.Resolve<IShoppingCartService>(); IProductMappingService _productMappingService = EngineContext.Current.Resolve<IProductMappingService>(); IAttributeValueService _attributeValueService = EngineContext.Current.Resolve<IAttributeValueService>(); IShippingService _shippingService = EngineContext.Current.Resolve<IShippingService>(); ICheckoutAttributeParser _checkoutAttributeParser = EngineContext.Current.Resolve<ICheckoutAttributeParser>(); ICheckoutAttributeService _checkoutAttributeService = EngineContext.Current.Resolve<ICheckoutAttributeService>(); IGiftCardService _giftCardService = EngineContext.Current.Resolve<IGiftCardService>(); ICountryService _countryService = EngineContext.Current.Resolve<ICountryService>(); IStateProvinceService _stateProvinceService = EngineContext.Current.Resolve<IStateProvinceService>(); IPluginFinder _pluginFinder = EngineContext.Current.Resolve<IPluginFinder>(); Customer customer = _workContext.CurrentCustomer; var basketResponse = _promoUtilities.GetBasketResponse(); // remove the previous response _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketResponse, null, _storeContext.CurrentStore.Id); IList<BasketRequestItem> items = new List<BasketRequestItem>(); Decimal orderTotal = Decimal.Zero; #region remove any items added by promo engine // remove any items added by promo engine that were NOT split from the original basket // get the selectedShippingOption - if it's not null will need to save this after removing products from the cart ShippingOption selectedShippingOption = _workContext.CurrentCustomer.GetAttribute<ShippingOption>(SystemCustomerAttributeNames.SelectedShippingOption, _storeContext.CurrentStore.Id); if (basketResponse != null && basketResponse.Items != null) { var generatedItems = (from bri in basketResponse.Items where bri.SplitFromLineId == 0 && bri.Generated && !bri.IsDelivery select bri).ToList(); foreach (var generatedItem in generatedItems) { int productId = 0; if (!int.TryParse(generatedItem.ProductCode, out productId)) { var attributeValueMappingItems = _attributeValueService.RetrieveAllForAttribute(EntityAttributeName.CheckoutAttribute); var attributeValueMappingItem = (from ca in attributeValueMappingItems where ca.Code.Equals((generatedItem.ProductCode ?? string.Empty), StringComparison.InvariantCultureIgnoreCase) select ca).FirstOrDefault(); if (attributeValueMappingItems == null) throw new KeyNotFoundException(string.Format("No attributeValueMappingItem for product code {0}", generatedItem.ProductCode)); } else { Product product = _productService.GetProductById(productId); ProductMappingItem productMappingItem = _productMappingService.RetrieveFromVariantCode(productId, generatedItem.VariantCode); string attributesXml = string.Empty; if (productMappingItem != null) attributesXml = productMappingItem.AttributesXml; var addedItem = _shoppingCartService.FindShoppingCartItemInTheCart(cart, ShoppingCartType.ShoppingCart, product, attributesXml); if (addedItem != null) { int generatedItemQuantity = Decimal.ToInt32(generatedItem.Quantity); int newQuantity = addedItem.Quantity - generatedItemQuantity; _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer, addedItem.Id, addedItem.AttributesXml, addedItem.CustomerEnteredPrice, addedItem.RentalStartDateUtc, addedItem.RentalEndDateUtc, newQuantity, false); } } } } cart = customer.ShoppingCartItems.ToList(); if (selectedShippingOption != null) _genericAttributeService.SaveAttribute<ShippingOption>(_workContext.CurrentCustomer, SystemCustomerAttributeNames.SelectedShippingOption, selectedShippingOption, _storeContext.CurrentStore.Id); #endregion #region build basket items // If we no longer have items in the shopping cart, do not return a basket Request so we don't call Promo unnecessarily if (cart.Count < 1) return null; foreach (var shoppingCartItem in cart) { Product product = _productService.GetProductById(shoppingCartItem.ProductId); string productCode = product.Id.ToString(); string barcode = product.Gtin; string variantCode = string.Empty; var productMappingItem = _productMappingService.RetrieveFromShoppingCartItem(shoppingCartItem); if (productMappingItem != null) variantCode = productMappingItem.VariantCode; // DM Cope with baskets in current currency decimal usePrice = _priceCalculationService.GetUnitPrice(shoppingCartItem, includeDiscounts: false); if (_promoSettings.UseSelectedCurrencyWhenSubmittingBaskets && _workContext.WorkingCurrency.Rate != 1) usePrice = _currencyService.ConvertFromPrimaryExchangeRateCurrency(usePrice, _workContext.WorkingCurrency); BasketRequestItem item = new BasketRequestItem() { // Hotfix - 2016-10-17 - START //Barcode = barcode, // Hotfix - 2016-10-17 - END Id = shoppingCartItem.Id, Price = usePrice, ProductCode = productCode, Quantity = (byte)shoppingCartItem.Quantity, VariantCode = variantCode }; items.Add(item); // DM Cope with baskets in current currency decimal subTotalAmount = _priceCalculationService.GetSubTotal(shoppingCartItem, includeDiscounts: false); if (_promoSettings.UseSelectedCurrencyWhenSubmittingBaskets && _workContext.WorkingCurrency.Rate != 1) subTotalAmount = _currencyService.ConvertFromPrimaryExchangeRateCurrency(subTotalAmount, _workContext.WorkingCurrency); orderTotal += subTotalAmount; } #endregion #region coupons IList<BasketRequestCoupon> coupons = new List<BasketRequestCoupon>(); string discountcouponcode = customer.GetAttribute<string>(SystemCustomerAttributeNames.DiscountCouponCode); if (!string.IsNullOrEmpty(discountcouponcode)) { BasketRequestCoupon coupon = new BasketRequestCoupon() { Code = discountcouponcode, }; coupons.Add(coupon); } #endregion #region shipping ShippingOption shippingOption = (selectedShippingOption != null ? selectedShippingOption : GetDefaultShippingOption(_shippingService, _workContext, _storeContext, _countryService, _stateProvinceService, _genericAttributeService)); string shippingOptionName = (shippingOption != null ? shippingOption.Name : string.Empty); string shippingIntegrationCode = shippingOptionName; // Is there an Integration code for the specified shipping option? IList<ShippingMethod> shippingMethods = _shippingService.GetAllShippingMethods(); var specifiedShippingMethod = (from sm in shippingMethods where sm.Name.Equals(shippingOptionName, StringComparison.InvariantCultureIgnoreCase) select sm).FirstOrDefault(); if (specifiedShippingMethod != null) { // TODO: why is there a namespace issue here? Qixol.Nop.Promo.Core.Domain.AttributeValues.AttributeValueMappingItem integrationMappingItem = _attributeValueService.Retrieve(specifiedShippingMethod.Id, EntityAttributeName.DeliveryMethod); if (integrationMappingItem != null && !string.IsNullOrEmpty(integrationMappingItem.Code)) shippingIntegrationCode = integrationMappingItem.Code; } decimal deliveryPrice = 0M; string deliveryMethod = string.Empty; if (cart.RequiresShipping()) { global::Nop.Core.Domain.Discounts.Discount appliedDiscount = null; deliveryPrice = _orderTotalCalculationService.AdjustShippingRate(selectedShippingOption != null ? selectedShippingOption.Rate : 0M, cart, out appliedDiscount); // DM Cope with baskets in current currency if (_promoSettings.UseSelectedCurrencyWhenSubmittingBaskets && _workContext.WorkingCurrency.Rate != 1) deliveryPrice = _currencyService.ConvertFromPrimaryExchangeRateCurrency(deliveryPrice, _workContext.WorkingCurrency); deliveryMethod = shippingIntegrationCode; orderTotal += deliveryPrice; } #endregion #region customer role mapping AttributeValueMappingItem customerGroupAttributeValueMappingItem = null; string customerGroupIntegrationCode = string.Empty; int priority = int.MinValue; foreach (CustomerRole customerRole in customer.CustomerRoles) { AttributeValueMappingItem attributeValueMappingItem = _attributeValueService.Retrieve(customerRole.Id, EntityAttributeName.CustomerRole); if (attributeValueMappingItem != null && !string.IsNullOrEmpty(attributeValueMappingItem.Code)) { if (attributeValueMappingItem.Priority.HasValue) { if (attributeValueMappingItem.Priority.Value > priority) { priority = attributeValueMappingItem.Priority.Value; customerGroupAttributeValueMappingItem = attributeValueMappingItem; } } else { customerGroupAttributeValueMappingItem = attributeValueMappingItem; } } } if (customerGroupAttributeValueMappingItem != null) { customerGroupIntegrationCode = customerGroupAttributeValueMappingItem.Code; } #endregion #region store mapping string storeIntegrationCode = string.Empty; AttributeValueMappingItem storeAttributeValueMappingItem = _attributeValueService.Retrieve(_storeContext.CurrentStore.Id, EntityAttributeName.Store); if (storeAttributeValueMappingItem != null && !string.IsNullOrEmpty(storeAttributeValueMappingItem.Code)) storeIntegrationCode = storeAttributeValueMappingItem.Code; #endregion #region checkout attributes string checkoutAttributesXml = _workContext.CurrentCustomer.GetAttribute<string>(SystemCustomerAttributeNames.CheckoutAttributes, _genericAttributeService, _storeContext.CurrentStore.Id); List<CheckoutAttribute> checkoutAttributes = _checkoutAttributeParser.ParseCheckoutAttributes(checkoutAttributesXml).ToList(); int basketItemId = (from i in items orderby i.Id descending select i.Id).FirstOrDefault(); foreach (CheckoutAttribute checkoutAttribute in checkoutAttributes) { List<string> checkoutAttributeValueIds = _checkoutAttributeParser.ParseValues(checkoutAttributesXml, checkoutAttribute.Id).ToList(); decimal priceAdjustment = decimal.Zero; foreach (string checkoutAttributeValueId in checkoutAttributeValueIds) { int id; if (int.TryParse(checkoutAttributeValueId, out id)) { CheckoutAttributeValue checkoutAttributeValue = _checkoutAttributeService.GetCheckoutAttributeValueById(id); if (checkoutAttributeValue.PriceAdjustment > 0) { priceAdjustment += checkoutAttributeValue.PriceAdjustment; } } } string checkoutAttributeValueVariantCode = null; if (checkoutAttributeValueIds.Count == 1) { checkoutAttributeValueVariantCode = checkoutAttributeValueIds.First(); } if (priceAdjustment > decimal.Zero) { basketItemId++; // DM Cope with baskets in current currency if (_promoSettings.UseSelectedCurrencyWhenSubmittingBaskets && _workContext.WorkingCurrency.Rate != 1) priceAdjustment = _currencyService.ConvertFromPrimaryExchangeRateCurrency(priceAdjustment, _workContext.WorkingCurrency); BasketRequestItem checkoutAttributeBasketItem = new BasketRequestItem() { Id = basketItemId, ProductCode = checkoutAttribute.ProductCode(), VariantCode = checkoutAttributeValueVariantCode, Price = priceAdjustment, Quantity = 1, IsDelivery = false }; items.Add(checkoutAttributeBasketItem); orderTotal += priceAdjustment; } } #endregion #region gift cards // DO NOT APPLY GIFT CARDS at this point // as they are a form of tender, only send with a confirmed basket // the promo engine needs the full ordertotal for calculations #region Applied gift cards //decimal resultTemp = orderTotal; //List<BasketRequestCustomAttribute> customAttributes = new List<BasketRequestCustomAttribute>(); //List<AppliedGiftCard> appliedGiftCards = new List<AppliedGiftCard>(); //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 (resultTemp > decimal.Zero) // { // decimal remainingAmount = gc.GetGiftCardRemainingAmount(); // decimal amountCanBeUsed = decimal.Zero; // if (resultTemp > remainingAmount) // amountCanBeUsed = remainingAmount; // else // amountCanBeUsed = resultTemp; // //reduce subtotal // resultTemp -= amountCanBeUsed; // var appliedGiftCard = new AppliedGiftCard(); // appliedGiftCard.GiftCard = gc; // appliedGiftCard.AmountCanBeUsed = amountCanBeUsed; // appliedGiftCards.Add(appliedGiftCard); // } // } // customAttributes.Add(new BasketRequestCustomAttribute() // { // Name = "giftcardscanbeused", // Value = "true" // }); // customAttributes.Add(new BasketRequestCustomAttribute() // { // Name = "giftcardscanbeusedvalue", // Value = appliedGiftCards.Sum(agc => agc.AmountCanBeUsed).ToString() // }); // } //} //if (resultTemp < decimal.Zero) // resultTemp = decimal.Zero; ////if (_shoppingCartSettings.RoundPricesDuringCalculation) //// resultTemp = RoundingHelper.RoundPrice(resultTemp); //orderTotal = resultTemp; #endregion #endregion #region basket var basketUniqueReference = _workContext.CurrentCustomer.GetAttribute<Guid>(PromoCustomerAttributeNames.PromoBasketUniqueReference, _storeContext.CurrentStore.Id); if (basketUniqueReference == Guid.Empty) { basketUniqueReference = Guid.NewGuid(); _genericAttributeService.SaveAttribute<Guid>(customer, PromoCustomerAttributeNames.PromoBasketUniqueReference, basketUniqueReference, _storeContext.CurrentStore.Id); } BasketRequest basketRequest = new BasketRequest() { Id = basketUniqueReference.ToString(), CompanyKey = _promoSettings.CompanyKey, CustomerId = customer.Id.ToString(), BasketTotal = orderTotal, SaleDateTime = DateTime.UtcNow, Store = storeIntegrationCode, StoreGroup = _promoSettings.StoreGroup, Channel = _promoSettings.Channel, CustomerGroup = customerGroupIntegrationCode, DeliveryPrice = deliveryPrice, DeliveryMethod = shippingIntegrationCode, Coupons = coupons.ToList(), Items = items.ToList(), //CustomAttributes = customAttributes, Confirmed = false, CurrencyCode = _workContext.WorkingCurrency != null ? _workContext.WorkingCurrency.CurrencyCode : string.Empty }; // DM Cope with baskets in current currency // Add a flag to the basket request indicating whether the values have been passed in customer currency or not. // This will be used when we are extracting values from the cached basket response, but may also be useful on the Promo side in the future (i.e. // when setting up promotions!). basketRequest.AddCustomAttribute("incustomercurrency", _promoSettings.UseSelectedCurrencyWhenSubmittingBaskets.ToString()); // Add identifier for integration source ("nopCommerce") var promoPlugin = _pluginFinder.GetPluginDescriptorBySystemName("Misc.QixolPromo"); basketRequest.AddCustomAttribute("integrationsource", string.Format("nopCommerce - plugin v{0}", promoPlugin.Version)); string basketRequestString = basketRequest.ToXml(); _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketRequest, basketRequestString, _storeContext.CurrentStore.Id); #endregion return basketRequest; }