Is this really the version you are looking for? Kentico Xperience 11 Documentation is no longer updated. Use the switcher in the header to choose your product version.
The Kentico E-commerce Solution allows you to customize how the system applies discounts to products and orders. For example, you can:
Note: If you only need to set up custom conditions under which discounts are applied, you may be able to achieve your goal by creating discount macro rules.
To customize discounts:
Open your Kentico project in Visual Studio.
Create new classes that implement one or more of the discount customization interfaces (described below).
Class location
For production sites, we recommend creating a new assembly (Class library project) in your Kentico solution and including the classes there. Then, add the appropriate references to both the assembly and the main Kentico web project. For more information, see Best practices for customization.
Implement all methods required by the given interfaces.
Register your implementations of the interfaces using the RegisterImplementation assembly attribute.
When you reload the website, the system uses the custom implementations that you registered instead of the default discount functionality.
All mentioned interfaces can be found in the CMS.Ecommerce namespace.
The system uses the following interfaces to load discounts that apply to individual units of products (includes Catalog and Volume discounts by default):
The PriceParameters parameter available in the methods of ICatalogDiscountSource and IProductDiscountSource provides the following properties:
See the following customization examples:
The E-commerce API uses the following additional interfaces to connect the discount sources with the overall product price calculation logic (see Customizing product prices to learn more):
Customization of these interfaces is not required or recommended for typical discount customization scenarios.
The system uses the IProductCouponSource interface to load discounts that require a coupon code and apply to shopping cart lines (each line represents one or more units of a product). See Working with product coupons to learn about the default functionality.
The IProductCouponSource interface is only intended for customization scenarios that utilize the default Kentico product coupon objects (i.e. objects represented by the MultiBuyDiscountInfo class in the API and managed in the Product coupons application of the administration interface).
If you need to integrate product coupons from an external source or service, we recommend adding a custom step (IShoppingCartCalculator implementation) into the overall shopping cart calculation process. See Customizing the shopping cart calculation for more information.
Implementations of IProductCouponSource must contain the GetDiscounts method. The method provides a DiscountsParameters parameter with the following properties:
The GetDiscounts method must return an IEnumerable collection of IMultiBuyDiscount objects representing the applied discounts (we recommended using instances of the default MultiBuyDiscount class).
The E-commerce API additionally uses the IMultiBuyDiscountsApplicator and IProductCouponService interfaces to connect the product coupon source with the overall shopping cart and order calculation logic. However, customization of these interfaces is not required for typical scenarios. For such advanced cases, we instead recommend adding a custom step (IShoppingCartCalculator implementation) into the overall shopping cart calculation process (see Customizing the shopping cart calculation for more information).
The system uses the IMultiBuyDiscountSource interface to load discounts that work based on combinations of products and apply to shopping cart lines (each line represents one or more units of a product). See Working with Buy X Get Y discounts to learn about the default functionality.
Implementations of IMultiBuyDiscountSource must contain the GetDiscounts method, which provides a DiscountsParameters parameter (see the Product coupons section to learn about the available properties). The GetDiscounts method must return an IEnumerable collection of IMultiBuyDiscount objects representing the applied discounts (we recommended using instances of the default MultiBuyDiscount class).
If you need to modify how the system evaluates whether the content of a shopping cart is eligible for a Buy X Get Y discount, create a custom implementation of the IMultiBuyDiscountsEvaluator interface. We recommend using the following general approach:
The E-commerce API additionally uses the IMultiBuyDiscountsApplicator and IMultiBuyDiscountsService interfaces to connect the Buy X Get Y functionality with the overall shopping cart and order calculation logic. However, customization of these interfaces is not required for typical scenarios. For such advanced cases, we recommend implementing your custom discount functionality as a separate step (IShoppingCartCalculator implementation) in the overall shopping cart calculation process. See Customizing the shopping cart calculation for more information.
The system uses the IOrderDiscountSource interface to load discounts that apply to entire orders/purchases (Order discounts by default). Implementations must contain the GetDiscounts method, which provides the following parameters:
The GetDiscounts method must return an IEnumerable collection of DiscountCollection objects representing the applied discounts.
The E-commerce API uses the general IDiscountApplicator interface to connect the order discount source with the overall shopping cart and order calculation logic (see Customizing the shopping cart calculation to learn more).
Implementations of IDiscountApplicator must contain the ApplyDiscounts method, which performs the following functions:
Customization of this interface is not required or recommended for typical discount customization scenarios.
The system uses the IShippingDiscountSource interface to load discounts that apply to shipping costs (Free shipping offers by default). Implementations must contain the following methods:
The E-commerce API uses the following additional interfaces to connect the shipping discount source with the overall shopping cart and order calculation logic (see Customizing the shopping cart calculation to learn more).
IDiscountApplicator – general service for applying multiple discounts (also used for product-level discounts and order discounts). Implementations must contain the ApplyDiscounts method, which performs the following functions:
IShippingPriceService – calculates the final shipping price. The default IShippingPriceService implementation gets shipping discounts using the registered IShippingtDiscountSource, and then creates the required shipping discount summary using the IDiscountApplicator implementation.
Customization of the IDiscountApplicator interface is not required or recommended for typical discount customization scenarios.
To learn more about customization of shipping cost customizations in general, refer to the Shipping-related customizing chapter.
The system uses the IGiftCardSource interface to load gift cards that reduce the final price of orders (see Working with gift cards to learn about the default functionality).
The IGiftCardSource interface is only intended for customization scenarios that utilize the default Kentico gift card objects (i.e. gift cards represented by the GiftCardInfo class in the API and managed in the Gift cards application of the administration interface).
If you need to integrate gift cards from an external source or service, we recommend adding a custom step (IShoppingCartCalculator implementation) into the overall shopping cart calculation process. See Customizing the shopping cart calculation for more information.
Implementations of IGiftCardSource must contain the GetGiftCards method, which provides the following parameters:
The GetGiftCards method must return an IEnumerable collection of GiftCardApplication objects representing the applied gift cards.
The following example demonstrates how to implement a custom product-level discount. This customization applies all valid catalog and volume discounts from Kentico, and then additionally reduces the price of all products by 10% for customers who are registered users on the website.
Prepare a separate project for custom classes in your Kentico solution:
Open your Kentico solution in Visual Studio.
Create a new Class Library project in the Kentico solution (or reuse an existing custom project).
Add references to the required Kentico libraries (DLLs) for the new project:
Right-click the project and select Add -> Reference.
Select the Browse tab of the Reference manager dialog, click Browse and navigate to the Lib folder of your Kentico web project.
Add references to the following libraries (and any others that you may need in your custom code):
Reference the custom project from the Kentico web project (CMSApp or CMS).
Edit the custom project's AssemblyInfo.cs file (in the Properties folder).
Add the AssemblyDiscoverable assembly attribute:
using CMS;
[assembly:AssemblyDiscoverable]Continue by creating a custom implementation of the IProductDiscountSource interface:
Add a new class under the custom project, inheriting from the default ProductDiscountSource class (and implementing the IProductDiscountSource interface).
using System.Collections.Generic;
using CMS;
using CMS.Ecommerce;
// Registers the custom implementation of IProductDiscountSource
[assembly: RegisterImplementation(typeof(IProductDiscountSource), typeof(CustomProductDiscountSource))]
public class CustomProductDiscountSource : ProductDiscountSource, IProductDiscountSource
{
/// <summary>
/// Constructor with parameters that accept instances of services required by the ProductDiscountSource base class.
/// </summary>
public CustomProductDiscountSource(ICatalogDiscountSource catalogDiscountSource, IVolumeDiscountSource volumeDiscountSource, ISiteMainCurrencySource mainCurrencySource, ICurrencyConverterFactory currencyConverterFactory, IRoundingServiceFactory roundingServiceFactory)
: base(catalogDiscountSource, volumeDiscountSource, mainCurrencySource, currencyConverterFactory, roundingServiceFactory)
{
}
/// <summary>
/// Creates a collection of product-level discounts that apply to a specified product.
/// Additional data related to the price and purchase context is provided in the PriceParameters.
/// </summary>
public override IEnumerable<DiscountCollection> GetDiscounts(SKUInfo sku, decimal standardPrice, PriceParameters priceParams)
{
var discountGroups = new List<DiscountCollection>();
// Adds the default Kentico catalog and volume discounts (using methods from the ProductDiscountSource base class)
AddCatalogDiscounts(discountGroups, sku, priceParams);
AddVolumeDiscounts(discountGroups, sku, priceParams);
// Adds a custom discount
// The custom discount uses multiplicative stacking with any applied catalog or volume discounts
// (i.e. the custom discount is calculated from the price reduced by other discounts)
AddCustomDiscounts(discountGroups, sku, priceParams);
return discountGroups;
}
/// <summary>
/// Adds a custom discount for a specified product.
/// </summary>
private void AddCustomDiscounts(List<DiscountCollection> discountGroups, SKUInfo sku, PriceParameters priceParams)
{
// Adds the discount only for customers who are registered users on the website
if (priceParams.User != null)
{
// Creates a 10% custom discount (using a method from the ProductDiscountSource base class)
IDiscount customDiscount = CreatePercentageProductDiscount("Discount for registered users", 0.1m, priceParams);
// Adds the custom discount to the collection of overall product discounts
var discountCollection = new DiscountCollection(new[] { customDiscount });
discountGroups.Add(discountCollection);
}
}
}Save all changes and Build the custom project.
The registered CustomProductDiscountSource implementation extends the Kentico product-level discounts. The custom discount source retains the default catalog and volume discount functionality by inheriting from the ProductDiscountSource class (the default implementation of IProductDiscountSource). The added custom discount affects both price calculations during the checkout process and prices displayed in product catalogs on the live site (when using appropriate transformation methods).
The following example demonstrates how to override the default volume discount functionality of Kentico. The example defines the volume discount rules directly in the code, but you can use the same basic approach to load the discount parameters from an external source or service.
using CMS;
using CMS.Ecommerce;
// Registers the custom implementation of IVolumeDiscountSource
[assembly: RegisterImplementation(typeof(IVolumeDiscountSource), typeof(CustomVolumeDiscountSource))]
public class CustomVolumeDiscountSource : IVolumeDiscountSource
{
/// <summary>
/// Returns an appropriate volume discount for a specified product (SKU) and unit quantity.
/// </summary>
public VolumeDiscountInfo GetDiscount(SKUInfo sku, decimal quantity)
{
// No volume discount applies if the unit quantity is lower than 3
if (quantity < 3)
{
return null;
}
// Defines a custom volume discount
// The discount value is percentage-based, calculated according to the purchased unit quantity
var customVolumeDiscount = new VolumeDiscountInfo
{
VolumeDiscountSKUID = sku.SKUID,
VolumeDiscountMinCount = 3,
VolumeDiscountIsFlatValue = false,
VolumeDiscountValue = GetDiscountValue(quantity)
};
return customVolumeDiscount;
}
/// <summary>
/// Calculates the volume discount value based on the unit quantity.
/// </summary>
private decimal GetDiscountValue(decimal quantity)
{
// 5% discount if the unit quantity is at least 3, but below 5
if (quantity < 5)
{
return 5m;
}
// 10% discount if the unit quantity is at least 5, but below 10
if (quantity < 10)
{
return 10m;
}
// 15% discount if the unit quantity is at least 10, but below 15
if (quantity < 15)
{
return 15m;
}
// 20% discount for 15 or more units
return 20m;
}
}The registered CustomVolumeDiscountSource implementation fully replaces the default Kentico volume discounts. When a customer adds the required number of product units to their shopping cart, the system automatically applies the corresponding discount to the unit price. Any volume discounts defined in the Kentico administration interface no longer apply.