Lee Willis

Virtuemart Category Discounts



Virtuemart is an excellent Open Source e-Commerce system that integrates with the Joomla content management system. I use it on a number of sites – some with more challenging eCommerce requirements than others.

While Virtuemart offers bulk purchase discounts (£10 each, or 3 or £27 style offers) – it unfortunately only implements these on a per-product basis. This is great if you want to order 3 of the exact same pair of baby shoes.

However, a common request is to implement category-based discounts, so  for example you would be able to offer a discount where people buy multiple products from a particular category.

We do just this on SnugBaby, where we periodically run category based discounts on our baby shoes, where the requirement is that you get a discount if you choose to buy multiple products from a particular category.


There are some caveats to the approach we’re going to describe below:

  1. It involves patching the Virtuemart source files  – this is not a Plugin, Component, or module. You should attempt this only if you’re comfortable editing PHP code
  2. Further to the above – if you upgrade Virtuemart this will need re-applying, possibly with some tweaks and tickles
  3. This assumes you’re running Virtuemart 1.1.3 (Although the theory of the approach works with VM 1.0.x as well)


This approach uses the Virtuemart bulk pricing model to store the bulk prices. This means you need to go through the products that are on special offer and add in the bulk prices. In the example I’m going to use here we are selling baby shoes. The standard price is £16.50 per pair, but if you buy more than 1 pair (Of any design), then you get them for £15.00 per pair.

We market this as “2 for £30” – however the reality (Probably should be caveat number 4!) is that it becomes £15 per pair for any number of shoes 2 and over (E.g. you could get 3 pairs for £45, 4 pairs for £60 and so on …).

So. First things first. Add the pricing to Virtuemart. If you’ve never done bulk pricing in Virtuemart here’s a quick guide. For each of your products in turn, edit the product, and choose “List Prices”:


Then you’ll need to specify your pricing:


Once this is done then your customers can get the special price, but only if they buy 2 or more of the same product.

The fun part

We can make all the changes we need to in just one file, administrator/components/com_virtuemart/classes/ps_product.php. This file is responsible for calculating product pricing, taking into account quantity discounts. The function in question is get_price().

This function out-of-the-box is given a product ID and is asked to calculate the price. It has a section relating to quantity pricing which roughly follows the following logic:

– Cycle through all cart contents

– If the product_id of the cart item matches the product_id we’re trying to cost then sum up the quantity of this item

– Retrieve the product price based on total volume of a product in the cart

We’re going to amend the second step such that it sums up the quantities of all products in the same category as the product we’re trying to cost.

The full patch (For the impatient) is here.

The patch is split into 2 main sections. The first gets the category that the product we’re costing belongs to (Caveat #5 – I have no idea what happens if your bulk purchase products are in multiple categories!). It also checks if that category is eligible for bulk discounts. You’ll need to change the 28 below to match your category ID.

Line 1608:
// Get the product_parent_id for this product/item
$product_parent_id = $this->get_field($product_id, “product_parent_id”);
// LW PATCH – Get the category of this product – used later to drive category-based multiple purchases
$sesq = “SELECT category_id FROM #__{vm}_product_category_xref WHERE product_id=’$product_id'”;
$db->setQuery($sesq); $db->query();
$sesprodcat = $db->f(“category_id”);
if ($sesprodcat == 28) {
$ses_cat_discount = TRUE;
} else {
$ses_cat_discount = FALSE;

The next section changes the calculation so that instead of comparing the product IDs, we comapre category IDs:

Line 1622:
// LW PATCH – If any product in the cart is in the same category then treat as volume purchase
if ($ses_cat_discount) {
  $sesq = “SELECT category_id FROM #__{vm}_product_category_xref WHERE product_id='”.$cart[$i][“product_id”].”‘”;
  $db->setQuery($sesq); $db->query();
  $sesprodchildcat = $db->f(“category_id”);
  if ($sesprodchildcat == $sesprodcat) {
    $quantity += $cart[$i][“quantity”];
} else {

  if ($cart[$i][“product_id”] == $product_id) {
    if ($parent) {
      $parent_id = $cart[$i][“parent_id”];
Line 1631:

And that’s that. Give it a try, let me know what you think!


Leave a Reply

Required fields are marked *.