Pricing Rules with Multiple-Product Quantity Condition

The quick and dirty:
I'm trying to create flexible mix-and-match pricing rules/discounts based on the combined quantity of a subset of products in the cart. Some discounts will be on a group of specific products, some on all products of a certain type, and some on products of multiple types.

For example, if a customer is ordering products in a defined group (a specific calendar and/or specific datebook; any button and/or any sticker) with a combined quantity of 5-10 in any mixture/configuration, all products in the group get discounted by $2.


What I've been trying:
• I have discounts, total order quantity, and quantity of one particular product fine.

• I thought the condition "Order contains a particular product" might accept multiple products (one on each line of the text area) but this isn't the case.

• I tried setting OR conditions to filter each particular product, then creating a number variable and adding the quantities of each product in the group together with actions. Since rules on event "Calculating sell price of product" run separately on each line item it wasn't combining the quantities; running the calculation in a loop on Line Items resulted in the quantity of the current Line Item the rule was acting on being multiplied by the number of line items, never adding quantities from different product line items.

• I'm thinking of creating Rules Components, which would give me configured routines I can call from each separate discount pricing rule, and I'm thinking these need to be acting on the order entity level to evaluate all products in the order together, while the pricing rule remains at the line item level. I'm also thinking I may need to throw the group of products into a list variable at some point in the process.


I'm familiar with Rules on D6, but I'm new to D7 as well as Drupal Commerce (and cart systems in general). Being new to D7, I'm still figuring out the whole Components thing, as well as Entities; I'm not sure if my difficulty is a result of not being familiar with these things, or if it even can be done at all without the use of extra modules (which is a possible option). I could use custom PHP conditions and actions, or look into Views/Rules integration to bring in some queries to work with, or use Commerce Extra Rules Conditions, but I'm wondering if there's a way to do it without those things.

I'm really looking to wrap my head around the logic of these various pieces. I've tried looking around but haven't been able to find much of anything specific about conditions to check the combined total of multiple products (I did find http://www.drupalcommerce.org/discussions/789/rules-commerce-stock-how-s..., but the logic discussed there is based on using taxonomy – I'm wondering if there is an even more flexible way to do this).

Posted: Oct 18, 2012


rvallejo on October 18, 2012

Looking more at the Commerce Extra Rules Conditions module more, it looks like it can handle combined quantities based on both taxonomy and product type (I thought it was limited to Taxonomy at first), but it still doesn't handle defining specific SKUs, which may or may not be necessary as I get more into all the specific discounts, and the module seems to be abandoned for almost a year now in dev.

So, suggestions still greatly appreciated, and if anyone wants to take on maintaining that module, it seems like it would be a good benefit to the community.

rvallejo on November 7, 2012

I tried out the Commerce Rules Conditions module, which provided a fairly easy setup, but didn't allow for mix and match by SKU, and hasn't been maintained for some time. So I set up a discount template using rules components. I'll post the rules exports and some description below in case anyone wants to play with it, is also looking for a core rules-based solution, or needs something more flexible.

Rules exports zip at google code: http://code.google.com/p/drupal-commerce-mix-and-match/downloads/list

The main product pricing rule is fairly simple, executing on event "price is calculated," (so, on each line item in the cart) just setting some basic conditions (line item is product, with a discounts taxonomy field), then declaring variables (criteria, quantity and price calculation) and calling the main rules component. Conditions for SKU/Type/Term can be added to speed up rules processing time but it's the variables that create the discount criteria. This leaves the setup of each discount to be fairly simple.

From there, I set up 7 rules components:

1) Action Set Component to define variables and provide some default values, called from the main pricing rule as the first action. Criteria variables are list variables to allow for multiple criteria of each type.

2) Action Set Component which loops on each cart item to generate a list of matches, called from the main pricing rule as the last action. This means while calculating the price for each item, the rule checks for matches on all other items for each of the criteria types, generates the list of matches, then loops on the list of matches to total the quantity of matching items.

3) Rule Component to check for SKU-based matches, which sets a SKU match truth value, called from the cart line item loop.

4) Rule Component to check for Type-based matches, which sets a type match truth value, called from the cart line item loop.

5) Rule Component to check for Term-based matches, which adds a term match truth value to a list of truth values, called from a loop on defined term criteria within the cart line item loop.

6) Rule Component to add line item to list of matches if it meets any of the defined criteria. Handling this separately from the criteria checks allows for the option of combining term and type criteria to be more selective, or being more inclusive using term OR type criteria (which is set using a truth value variable in the initial pricing rule to combine type/term criteria).

7) Rule Component to evaluate total quantity of matches, check if current line item is in the match list and set line item price to the calculated price change set in the initial pricing rule.

Additional notes: The variable "Combine Type/Term" sets whether type and term criteria should be combined to be more exclusive, or not combined to be more inclusive. If the max quantity variable is set to 0, max quantity will be ignored. Any of the criteria can be left undefined. Obviously, for term criteria to work using the exports, you need to edit the rule and components to use your desired vocabulary (one condition in the initial pricing rule, and three conditions in the Term Matches rule component (#5)).

evanasse on January 15, 2013

Thanks for the rules. An error occurred when importing Default Mix and Match. Do I miss something like a module?

"Integrity check for the imported configuration failed. Error message: Unknown action component_rules_discount_variables"

evanasse on January 15, 2013

Another error importing Discount Loops. I badly need those rules :-)

"Integrity check for the imported configuration failed. Error message: Unknown action component_rules_discount_sku_matches"

rvallejo on January 22, 2013

Evanasse: You shouldn't need any extra modules, other than Rules and Commerce with Product/Product Pricing (which should all be installed and enabled anyway). My only immediate thought would be that you imported a rule or component which calls another component before importing the called component (from your comments, it looks like the issue was with a component each time). You should be able to import them all and then force an integrity check from the Rules admin page, or make sure to import the components in the right order before importing the main rule.

To avoid integrity issues, try importing in this order: 1) Discount Evaluate; 2) Discount Matches; 3) Discount Term Matches; 4) Discount Type Matches; 5) Discount SKU Matches; 6) Discount Loops; 7) Discount Variables; 8) Default Mix and Match.

Using the Features module, I created a widget that can be installed almost like a module if that would help.

Also, there are a couple spots you'll have to change a condition to whichever vocabulary you will be using. Edit the main pricing rule Default Mix and Match, second condition (Entity has field) and select your taxonomy field, then edit the Discount Term Matches rule component, third condition (Entity has field) and again select your taxonomy field.

FYI: there is now a Commerce Rules Extra module which is a maintained branch of the Commerce Extra Rules Conditions module with a stable release out.