Vote up!
Vote down!

How can I prevent the repurchase of products?

I just had the case where a customer accidentally bought two copies of the same downloadable file. I have done some research in the forums, but couldn't find any information on how to allow customers to buy products of a certain type only once.

I imagine it to work like this:

  • User adds a product of the type 'downloadable file' to the shopping cart
  • The 'add to cart' button get's blurred out and inactive (same as with the commerce stock module, where the button get's inactive when the stock reaches zero)
  • Once the product is purchased the button will always stay inactive for users that are logged in and have purchased the product previously
  • If a annonymous user attempts to buy the same 'downloadable file' again, the product is removed from the cart and the user is notified with a message that he has already purchased this product.

What would be the best way to create such a feature? Is there functionality within Commerce that can help here? Or would i have to use a combination of Rules and Views?

I'd appreciate any help very much!

Asked by: kleinermann
on July 26, 2013

3 Answers

Vote up!
Vote down!

You can get a lot of the way there just by using Rules and Views, which is why we designed Commerce the way we did. So there isn't going to be a setting or a single feature module that meets all these needs at once, but you can do some things like the following:

  1. You can prevent an item from being added to the cart by unsetting the product price for the item on the page using a product pricing rule. You'd do this by checking to see if the line item ID in the rule is 0, which means it's a temporary line item used to perform the price calculation. Then check to see if the product is already in the cart (or even purchased) and unset the price just like we do in the default pricing rule for when the product is disabled. That will automatically disable the button with the message "Product not available", so you'll likely want to do something to change that to a more meaningful message.
  2. You can also update your product display to not combine line items in the cart in the event that the user is able to find an Add to Cart button for the same product. Then you can disable the quantity textfield in the shopping cart form View so the user can't edit it, or you can do something like I demonstrate in this post to turn the textfield into a plaintext rendering of the quantity. You can also use Rules to react to the add to cart process and ensure the quantity of any related line items is 1.

There are drawbacks to using a pure UI approach. As I hinted in part 1, you're limited to what the button text can read. It should be different for different scenarios (already added vs. already purchased). Additionally, you don't have any way while users remain anonymous to inspect the orders in their session for products you know they've already purchased. That seems to me to be a fairly minor feature, though, as ideally they'd know they just purchased something - or else they could log in.

Ultimately, I think these needs would be best satisfied by a custom module that includes the code I mention from part 2 and supports configurable messages where applicable. I don't know of any such module or if these sorts of features are already extant in the 1.x of Commerce File.

Ryan Szrama
Answer by: Ryan Szrama
Posted: Jul 26, 2013
Vote up!
Vote down!

step 1:
open template.php in the theme you have decided to use in /sites/all/themes/xxx/template.php
add the following code at the bottom
function get_user_purchased_products(){
// Assuming we have $user populated with the user's ID:
global $user;
$query = db_select('commerce_order', 'cord');
$query->join('commerce_line_item', 'li', 'cord.order_id = li.order_id');
$query->join('field_data_commerce_product', 'prod', 'li.line_item_id = prod.entity_id');
$query->condition('cord.uid', $user->uid, '=')->condition('cord.status', 'completed', '=')->fields('prod', array('commerce_product_product_id'));
$result = $query->execute();
$purchased_products = array();
foreach($result as $oneResult){
array_push($purchased_products, $oneResult->commerce_product_product_id);
return $purchased_products;

import this rule and enjoy.
{ "rules_prevent_buying_an_already_purchased_product" : {
"LABEL" : "Prevent buying an already purchased product",
"PLUGIN" : "reaction rule",
"OWNER" : "rules",
"REQUIRES" : [ "php", "rules", "commerce_cart" ],
"ON" : { "commerce_cart_product_add" : [] },
"DO" : [
{ "php_eval" : { "code" : "global $pProducts;\r\n$pProducts = get_user_purchased_products();" } },
{ "LOOP" : {
"USING" : { "list" : [ "commerce-order:commerce-line-items" ] },
"ITEM" : { "list_item" : "Current list item" },
"DO" : [
{ "component_rules_check_if_cart_products_are_in_purchase_list" : { "line_item" : [ "list-item" ], "product" : [ "commerce-product" ] } }

what happens here is:

1- the rules gets called after adding the product to the shopping cart list.
2- it calls the function that loads all previously purchased product by the user and puts their ids in an array.
3- it loops in the shopping cart, extracting the product id from every line item and checking to see if this product is in the previously purchased product list.
4- if found, a message is fired and the product is removed from the list.

The idea is to come up with a solution that doesn't require you write a lot of php code so that if you want to update your modules later on or drupal core, you can do so without having to worry what will break.

i am building an online audio store and i have the same issue mentioned here and i have been googling for a way to do this for a few days now. a user buys an unlimited license for an audio track once in his life. no need to buy the same product again.

this worked for me, i hope it works for you as well.
i also hope drupal_commerce adds support for this later on, since it doesn't require much work, a simple function and a rule to be implemented :)

Answer by: mike.hajj
Posted: Apr 20, 2014


Unfortunately your solution doesn't work for me. It goes: "Integrity check for the imported configuration failed. Error message: Unknown action component_rules_check_if_cart_products_are_in_purchase_list.." while I am trying to import it. Anybody knows what's happening?

- pzo3xic on April 30, 2014
Vote up!
Vote down!

I get this error if I use your rule

Integrity check for the imported configuration failed. Error message: Unknown action <em class="placeholder">component_rules_check_if_cart_products_are_in_purchase_list</em>..

Any hints?

Answer by: Pauli
Posted: Jun 28, 2014