Pages - Menu

nopCommerce Discount Rules Plugin - Exclude Sale Products


Create a discount rule plugin that when a user create a discount, they have the option to add requirement whether to include sale products to the discount or not.

We are currently on the latest nopCommerce 3.3 platform, as of today.

How it works

I went through the source code of how other DiscountRules plugin works and concluded the followings:
  • The relationship between Discount and DiscountRequirement is just a one-to-many FK relationship. One Discount have many DiscountRequirements.
  • Any properties such as which customer role is required, or how much dollar value to pass the requirement rule is stored in setting.
  • The setting key is defined within the plugin and transparent from the calling controller / services.
  • In XxxDiscountRequirementRule.cs, we define CheckRequirement() that will return true / false if the requirement is fulfilled. It reads the relevant settings to check the properties such as dollar value or customer roles for passing the discount rule. 
  • The rule file must implement the IDiscountRequirementRule interface.
  • The pattern for how the settings are stored are generally in this format. string.Format("{0}", discountRequirement.Id)
  • There is an ajax call in the view that does a post back to the XxxController.Configure when saving the DiscountRequirement. 


Create the project

Following my previous post How to write a nopCommerce plugin I have created a new project called DiscountRules.SaleProduct from other DiscountRules plugin.


I added a boolean property in the RequirementModel to indicate if we want to include sale products.

public bool IncludeSales { get; set; }


The project I copied from were using DropDownList, I changed to CheckBox and modified the Ajax call that post back the property to the controller. Make sure to follow the pattern on suffixing the requirement id to the setting, as the screen can have multiple instance of the same rule.

Change the controller name in the ajax post back to match the new plugin name.


Modified the Configure method to work with the Ajax post back call. Make sure the parameter names match.


This CheckRequirement() method is the magic method that we will put our logics in checking sale items in the cart or not, and we will return true / false accordingly to exclude sale products from discount. Hopefully the customers still happy...

Depending on your implementations, the code might look like something below and could be very simple.
public bool CheckRequirement(CheckDiscountRequirementRequest request)

    foreach (var product in cart)
        if (product.SpecialPrice.GetValueOrDefault() > 0
            && product.SpecialPriceStartDateTimeUtc < DateTime.Now
            && product.SpecialPriceEndDateTimeUtc > DateTime.Now)
            return false;

    return true;


While in debug mode developing the plugin, if you found the plugin not reset properly even after you rebuild the solutions or clear cache. You could try to clear the Temporary ASP.NET Files folder. If you get access denied because it is being used, try delete the w3wp.exe from task manager. That will stop the IIS from accessing it.


  1. It is more appropriate to use iisreset to cycle IIS thereby releasing the .Net cache.