API
Version 7.x > API > Discounts on the fly? View modes: 
User avatar
Member
Member
sh_dev - 3/20/2013 7:40:50 PM
   
Discounts on the fly?
I have a unique situation when I need to apply a discount to a shoppingCartItem. The discount would be a flat value.
My assumption was that I would apply an ItemDiscount to the shoppingCartItem as the API reference docs indicate but that is not case.
var SCI = SHoppingCarInfoProvidert.GetSHoppngCartItemInfo(123);  //return a shoppingcartitemInfo

var ItemDiscount = new ItemDiscount();
ItemDisocount.ItemDiscountValue = GetAmt();
ItemDiscountID = "someId"

SCI.ApplyDiscount() // This does not exist.


private double GetAmt()
{
return 10000.00
}

Can someone explain how to go about setting a discount in this way to the shopping cart item and have the cart totals reflect these updates?

thanks
mac

User avatar
Member
Member
kentico_davidb2 - 3/21/2013 3:24:24 AM
   
RE:Discounts on the fly?
Hi mac,

Thank you for your message.

I would recommend trying to use CustomShoppingCartItemInfoProvider as the one placed in our sample codes (C:\Program Files (x86)\KenticoCMS\7.0\CodeSamples\App_Code Samples\E-commerce samples\CustomShoppingCartItemInfoProvider.cs) and overriding GetDiscountsInternal method, where you can add new discount to the discounts, which should be applied to the specified shopping cart item.

New discount (an example):
ItemDiscount discount = new ItemDiscount()
{
ItemDiscountID = discountId,
ItemDiscountDisplayName = "Product_discount_" + shoppingCartItem.SKUObj.SKUName,
ItemDiscountValue = 100,
ItemDiscountedUnits = shoppingCartItem.CartItemUnits,
ItemDiscountIsFlat = false,
ItemDiscountIsGlobal = false
};

and later:
//Add custom discount to discounts-list to be applied to the product
discounts.Add(discount);

Dave

User avatar
Member
Member
sh_dev - 3/21/2013 2:36:43 PM
   
RE:Discounts on the fly?
Hi David. Thank you for your concise reply. This is the approach I was taking earlier but for some reason the ShoppingCartInfo object fails to
A: reflect the discount in the product totals
B: maintain that state through the shopping cart wizard.
ShoppingCartInfoProvider.EmptyShoppingCart(ShoppingCart);

ShoppingCartItemInfo addedItem = ShoppingCart.SetShoppingCartItem(cartItemParams);

var total = ShoppingCart.TotalPrice; //57.00 at this time.
var discount = new ItemDiscount()
{
ItemDiscountID = Guid.NewGuid().ToString().Substring(0, 4),
ItemDiscountDisplayName = "discount" + addedItem.SKU.SKUName,
ItemDiscountValue = 10,
ItemDiscountedUnits = addedItem.CartItemUnits,
ItemDiscountIsFlat = false,
ItemDiscountIsGlobal = false
};


addedItem.ProductDiscounts.Add(discount); //note that this does NOT create a discount DataRow.

//Save the data to dataase
ShoppingCartItemInfoProvider.SetShoppingCartItemInfo(addedItem);

//the docs say this should apply/update all the items in the shopping cart.
ShoppingCartInfoProvider.EvaluateShoppingCart(ShoppingCart);

total = ShoppingCart.TotalPrice; //57.00 !!! its Still 57.00

I am sorry but I am just not seeing how the shopping cart applies these discounts or the method to call for it to do so.

sincerely
Mac

User avatar
Member
Member
kentico_davidb2 - 4/3/2013 3:58:10 AM
   
RE:Discounts on the fly?
Hi Mac,
I can see that you were solving this issue with Martin Danko.
Below is the working solution:

CustomShoppingCartItemInfoProvider.cs

using System;
using System.Collections.Generic;
using System.Web;
using System.Data;

using CMS.Ecommerce;
using CMS.SettingsProvider;
using CMS.SiteProvider;
using CMS.GlobalHelper;
using CMS.DataEngine;

/// <summary>
/// Sample shopping cart item info provider.
/// Can be registered either by replacing the ShoppingCartItemInfoProvider.ProviderObject (uncomment the line in SampleECommerceModule.cs) or through cms.extensibility section of the web.config
/// </summary>
public class CustomShoppingCartItemInfoProvider : ShoppingCartItemInfoProvider
{
private List<int> mPurchasedIDs = new List<int>();


private List<int> GetPurchasedProductsIds(int customerID)
{
if (mPurchasedIDs.Count == 0)
{
string query = string.Format("SELECT DISTINCT OrderItemSKUID FROM COM_OrderItem WHERE OrderItemOrderID IN (SELECT OrderID FROM COM_Order WHERE OrderCustomerID = {0})", customerID);

DataSet purchasedProducts = ConnectionHelper.ExecuteQuery(query, new QueryDataParameters(), QueryTypeEnum.SQLQuery, false);

if (!DataHelper.DataSourceIsEmpty(purchasedProducts))
// Process all rows
foreach (DataRow dr in purchasedProducts.Tables[0].Rows)
{
object value = dr["OrderItemSKUID"];
if (value != DBNull.Value)
{
int id = Convert.ToInt32(value);
if ((id > 0))
{
mPurchasedIDs.Add(id);
}
}
}
}

return mPurchasedIDs;
}


/// <summary>
/// Returns list of all discounts which should be applied to the specified shopping cart item.
/// </summary>
/// <param name="item">Shopping cart item</param>
protected override List<IItemDiscount> GetDiscountsInternal(ShoppingCartItemInfo item)
{
// Get default discounts
List<IItemDiscount> discounts = base.GetDiscountsInternal(item);

CustomerInfo customer = item.ShoppingCart.Customer;

if (customer != null)
{
List<int> purchasedProducts = GetPurchasedProductsIds(customer.CustomerID);

if ((item != null) && (purchasedProducts.Count > 0))
{
if (purchasedProducts.Contains(item.SKUID))
{
// Create flat discount
ItemDiscount discount = new ItemDiscount()
{
ItemDiscountID = "IsNotStoredInDB",
ItemDiscountDisplayName = string.Format("Discount for bundled purchase of product '{0}'", item.SKU.SKUName),
ItemDiscountValue = 20,
ItemDiscountIsFlat = true,
ItemDiscountedUnits = 1
};

// Add custom discount to discounts to be applied to the product
discounts.Add(discount);
}
}
}

return discounts;
}
}


SampleECommerceModule.cs

using System;

using CMS.Ecommerce;
using CMS.SettingsProvider;

/// <summary>
/// Sample e-commerce module class. Partial class ensures correct registration.
/// </summary>
[SampleECommerceModuleLoader]
public partial class CMSModuleLoader
{
#region "Macro methods loader attribute"

/// <summary>
/// Module registration
/// </summary>
private class SampleECommerceModuleLoaderAttribute : CMSLoaderAttribute
{
/// <summary>
/// Constructor
/// </summary>
public SampleECommerceModuleLoaderAttribute()
{
// Require E-commerce module to load properly
RequiredModules = new string[] { ModuleEntry.ECOMMERCE };
}


/// <summary>
/// Initializes the module
/// </summary>
public override void Init()
{
// -- Uncomment this line to register the CustomShippingOptionInfoProvider programmatically
//ShippingOptionInfoProvider.ProviderObject = new CustomShippingOptionInfoProvider();

// -- Uncomment this line to register the CustomShoppingCartInfoProvider programmatically
//ShoppingCartInfoProvider.ProviderObject = new CustomShoppingCartInfoProvider();

// -- Uncomment this line to register the CustomShoppingCartItemInfoProvider programmatically
ShoppingCartItemInfoProvider.ProviderObject = new CustomShoppingCartItemInfoProvider();

// -- Uncomment this line to register the CustomSKUInfoProvider programmatically
// SKUInfoProvider.ProviderObject = new CustomSKUInfoProvider();

// -- Uncomment this line to register the CustomTaxClassInfoProvider programmatically
//TaxClassInfoProvider.ProviderObject = new CustomTaxClassInfoProvider();

// -- Uncomment this line to register the CustomCustomerInfoProvider programmatically
//CustomerInfoProvider.ProviderObject = new CustomCustomerInfoProvider();

// -- Uncomment this line to register the CustomOrderInfoProvider programmatically
//OrderInfoProvider.ProviderObject = new CustomOrderInfoProvider();

// This line provides the ability to register the classes via web.config cms.extensibility section from App_Code
ClassHelper.OnGetCustomClass += GetCustomClass;
}


/// <summary>
/// Gets the custom class object based on the given class name. This handler is called when the assembly name is App_Code.
/// </summary>
private static void GetCustomClass(object sender, ClassEventArgs e)
{
if (e.Object == null)
{
// Provide your custom classes
switch (e.ClassName)
{
//// Define the class CustomShippingOptionInfoProvider inheriting the ShippingOptionInfoProvider and you can customize the provider
//case "CustomShippingOptionInfoProvider":
// e.Object = new CustomShippingOptionInfoProvider();
// break;

// Define the class CustomShoppingCartInfoProvider inheriting the ShoppingCartInfoProvider and you can customize the provider
//case "CustomShoppingCartInfoProvider":
// e.Object = new CustomShoppingCartInfoProvider();
// break;

// Define the class CustomShoppingCartItemInfoProvider inheriting the ShoppingCartItemInfoProvider and you can customize the provider
case "CustomShoppingCartItemInfoProvider":
e.Object = new CustomShoppingCartItemInfoProvider();
break;

//// Define the class CustomSKUInfoProvider inheriting the SKUInfoProvider and you can customize the provider
//case "CustomSKUInfoProvider":
// e.Object = new CustomSKUInfoProvider();
// break;

//// Define the class CustomTaxClassInfoProvider inheriting the TaxClassInfoProvider and you can customize the provider
//case "CustomTaxClassInfoProvider":
// e.Object = new CustomTaxClassInfoProvider();
// break;

//// Define the class CustomCustomerInfoProvider inheriting the CustomerInfoProvider and you can customize the provider
//case "CustomCustomerInfoProvider":
// e.Object = new CustomCustomerInfoProvider();
// break;

//// Define the class CustomOrderInfoProvider inheriting the OrderInfoProvider and you can customize the provider
//case "CustomOrderInfoProvider":
// e.Object = new CustomOrderInfoProvider();
// break;
}
}
}
}

#endregion
}


David