Zen Cart Logo
Forums / All Other Contributions/Addons / Limit Quantities for Downloads and Virtual Products [Support Thread]

Limit Quantities for Downloads and Virtual Products [Support Thread]

Views: 6,527

Results 1 to 20 of 48
26 Nov 2012, 4:16 PM
#1
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Limit Quantities for Downloads and Virtual Products [Support Thread]

I've just submitted v1.1.0 of this plugin to the Zen Cart Plugins for review ...

If your store has downloadable and/or virtual products, it's possible -- depending on your configuration -- for a customer to add multiple copies of the product to their cart. The customer can go through checkout confirmation, paying for the quantity present in their cart ... but when it comes to the download itself, only **one **copy is available for the customer to download.

Downloadable/virtual products can fall into three different customization types:

  1. The product is configured with a single attribute, e.g. one that specifies the download filename. For this type of product, you can use the built-in Zen Cart methods to limit the product to a single instance in a customer's cart. Use your admin's Catalog->Categories/Products and set:
  • Product Qty. Minimum to 1
  • Product Qty. Maximum to 1
  • Product Qty. Units to 1
  1. The product can be purchased either as a download or as a physical (e.g. printed) item. For this type of product, you probably want to allow multiple copies of the physical product to be placed into a customer's cart. Unfortunately, with this configuration the customer can also place multiple copies of the download version of the product in his/her cart ... possibly resulting in charge-back issues for your store.
  2. The downloadable/virtual product has multiple configurations, i.e. more than one attribute. For example, the product might be available in more than one language or in different file formats. The customer should be able to have different configurations of the product in his/her cart, but limited to a single instance for a specific attribute combination.

This plugin addresses customization types 2 and 3 described above and can be downloaded from: http://www.zen-cart.com/downloads.php?do=file&id=1018

20 Oct 2013, 5:32 PM
#2
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

I was peeking at this add-on, as you referenced it today on another thread, and it naturally grabbed my interest ... and I thought isn't this a nifty little add-on ... :cool:

It also is making me think about fun things for future updates of Zen Cart ...

But in testing it, I was running into things like when adding to the cart for the first time, and I try adding quantity 5, it would do that and only catch the need to fix the quantity to 1 if I then hit Update on the shopping cart or tried to add more to the cart the second time around, triggering the case for the update_product ...

I tried this on v1.5.1 and upcoming v1.5.2 and v1.6 with the same issue ...

Now I am not setting the Maximum to 1, but leaving it at 0, as I wanted a simple way to prevent the multiple order of quantity > 1 and also to not show that Max:1, I rather hate that at times, and keep the quantity box for Products that were Download/Physical based on the Attribute selected ...

So in fooling with this a bit further, I altered the case on add_product and changed it to:

  case 'add_product':
    if (isset($_POST['products_id']) && $_POST['cart_quantity'] > 0) {
      if (isset($_POST['id']) && $_SESSION['cart']->in_cart(zen_get_uprid($_POST['products_id'], $_POST['id']))) {
        foreach($_POST['id'] as $option => $value) {
          if (ldProductIsDownload ($_POST['products_id'], $option, $value)) {
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            zen_redirect(zen_href_link($goto, zen_get_all_get_params($parameters)));
          } else {
          }
        }
      } else {
        foreach($_POST['id'] as $option => $value) {
          if (ldProductIsDownload ($_POST['products_id'], $option, $value) && $_POST['cart_quantity'] > 1) {
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            $_POST['cart_quantity'] = 1;
          } else {
          }
        }
      }
    }
  break;

Now is it just in my testing that I am not fully understanding what you are doing here or did you write this with the understanding that all Download Products would be set to Max 1, even when there was also the alternative of offering things like Download on one Attribute and the CD on another ... or am I perhaps missing something on your intent ... :lookaroun

20 Oct 2013, 6:50 PM
#3
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Hmm, I'm not seeing that behavior when I choose 5 downloadable patterns on my needlework site. I've got min/max/units set to 1/0/1, respectively for the product. I also have "show the cart after add-to-cart" (or whatever that setting is), so when I add 5 to the cart I get the cart displayed with 1 item and a message " A downloadable product — <product name> — was not added to your cart. Your cart can hold at most one download of each product." displayed at the top of the shopping_cart page.

Let me see what's up ...

20 Oct 2013, 7:16 PM
#4
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

What version(s) are you testing in?

Also I may have 1 bug to work out on that add_product as I am getting on some versions the debug log message that could be due to customizations I am working on or an actually issue with this add-on and my code change ...

But let me know what you run into ...

My tests are based on the Download Products in the Demo data for:
/index.php?main_page=product_info&cPath=54_60&products_id=133
/index.php?main_page=product_info&cPath=54_60&products_id=179

20 Oct 2013, 7:23 PM
#5
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

I was testing on the original version of the plugin (the not-so-smart one). I've replicated the issue and am working towards a solution using some of the code fragments you provided ...

20 Oct 2013, 7:32 PM
#6
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Ahh! Good ... not my imagination ... hopefully you come up with a better fix and/or one that does not trip this debug error that I have ... hopefully that is just something I am doing in updating code or something fun ...

20 Oct 2013, 7:40 PM
#7
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Try this for the replacement for the add_product clause (it worked by me!). Essentially, I restructured the clause to first check to see if there's a download among the options and, if so, check to see if there's an instance already in the cart (in which case a redirect to the goto page occurs with no additional cart processing) or if there's not to reduce the quantity to 1 (with message) and let the base add_product processing perform its magic.

  /*---- Add a product to cart ----
  **
  ** If a product is being added to the cart (with a quantity greater than 0) and that product has attributes (the $_POST['id'] array
  ** is set), then if either that product is already in the cart -OR- if the quantity to be added is greater than 1,
  ** check each of the attributes being added to see if there is a download/virtual product amongst them.  If so,
  ** don't allow the duplicate download/virtual product to be added to the cart ... or just add 1 if this is the original add.
  */
  case 'add_product':
//-bof-v1.1.1c
    if (isset($_POST['products_id']) && $_POST['cart_quantity'] > 0 && isset($_POST['id']) && is_array($_POST['id'])) {
      foreach($_POST['id'] as $option => $value) {
        if (ldProductIsDownload ($_POST['products_id'], $option, $value)) {
          if ($_SESSION['cart']->in_cart(zen_get_uprid($_POST['products_id'], $_POST['id']))) {
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            zen_redirect(zen_href_link($goto, zen_get_all_get_params($parameters)));
            
          } elseif ($_POST['cart_quantity'] > 1) {
            $_POST['cart_quantity'] = 1;
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            
          }
          break;
        }
      }
    }
//-eof-v1.1.1c
  break;
```:
20 Oct 2013, 8:35 PM
#8
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Nope, it's close but not perfect. If the virtual/downloadable product includes a text attribute, the in_cart check indicates that the product's not in the cart ... when it is! That's because there's a mismatch between the uprid returned by the zen_get_uprid call and that present in the cart (due to the text attribute's value).

Still investigating ...

20 Oct 2013, 9:19 PM
#9
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Holy cr@p! I don't understand why this works and the previous version didn't, but it does. The uprid calculated by limit_downloads wasn't matching that present in the shopping_cart, so the in_cart test was failing. The values present in the $_POST['id'] array were identical to those present in the $attributes array processed by the shopping cart, the only difference is that a ***copy ***of the $_POST values was used. Making that modification magically makes the operation work properly.

I'm not a big fan of magic when it comes to code; if anyone can shed some light on why the updated version works while the previous version doesn't, I'd appreciate it!

  /*---- Add a product to cart ----
  **
  ** If a product is being added to the cart (with a quantity greater than 0) and that product includes attributes (the $_POST['id'] array
  ** is set), then if either that product is already in the cart -OR- if the quantity to be added is greater than 1,
  ** check each of the attributes being added to see if there is a download/virtual product amongst them.  If so,
  ** don't allow the duplicate download/virtual product to be added to the cart ... or just add 1 if this is the original add.
  */
  case 'add_product':
//-bof-v1.1.1c
    if (isset($_POST['products_id']) && $_POST['cart_quantity'] > 0 && isset($_POST['id']) && is_array($_POST['id'])) {
      $the_ids = $_POST['id'];
      foreach($_POST['id'] as $option => $value) {
        if (ldProductIsDownload ($_POST['products_id'], $option, $value)) {
          if ($_SESSION['cart']->in_cart(zen_get_uprid($_POST['products_id'], $the_ids))) {
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            zen_redirect(zen_href_link($goto, zen_get_all_get_params($parameters)));
            
          } elseif ($_POST['cart_quantity'] > 1) {
            $_POST['cart_quantity'] = 1;
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            
          }
          break;
        }
      }
    }
//-eof-v1.1.1c
  break;
21 Oct 2013, 12:16 AM
#10
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

It works on the 1st time you add from the Product page but if you go to the Product page again and do the add you continue to be able to get an additional Product in the cart ...

To replicate this, you need to be adding a Download Product that has 2 downloads like the Demo Product for:
/index.php?main_page=product_info&cPath=54_60&products_id=133

21 Oct 2013, 1:20 PM
#11
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Ajeh:

It works on the 1st time you add from the Product page but if you go to the Product page again and do the add you continue to be able to get an additional Product in the cart ...

To replicate this, you need to be adding a Download Product that has 2 downloads like the Demo Product for:
/index.php?main_page=product_info&cPath=54_60&products_id=133
Hmm, I'm not seeing that. If I add the English/PDF option it adds to cart. I return to the product page to add another English/PDF and get the "I limited your quantity" message and only 1 is in the cart. I return to the product page and add English/Word and it properly adds.

22 Oct 2013, 2:46 AM
#12
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Are you using this in Zen Cart v1.5 or v1.5.1 or which version ... I trip the error by add quantity 1 from:
/index.php?main_page=product_info&cPath=54_60&products_id=133

Then go to:
/index.php?main_page=product_info&cPath=54_60&products_id=133

and add quantity 1 and I now have 2 in the shopping_cart ...

This is in v1.5.1 and in v1.5 ...

Sorry I could not get to this earlier today ... :smile:

22 Oct 2013, 12:55 PM
#13
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Using ZC 1.5.1 (two localhost installations), PHP 5.3.8 (although I don't think that that's the difference). Using the following for /includes/extra_cart_actions/limit_downloads.php:

<?php
/**
 * Extra shopping Cart actions supported.
 *
 * @copyright Copyright 2009-2012 Vinos de Frutas Tropicales
 * @copyright Copyright 2003-2010 Zen Cart Development Team
 * @copyright Portions Copyright 2003 osCommerce
 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
 * @version $Id: limit_downloads.php 2012-11-26 lat9
 *
 * The main cart actions supported by the current shoppingCart class.
 *
 * This module checks for a downloadable and/or virtual product already present in the cart and disallows an additional product
 * quantities of the exactly-same configuration to be added.
 *
 * NOTE:  See also \includes\languages\english\extra_definitions\YOURTEMPLATE\limit_downloads.php for language constants.
 *
 */

switch ($_GET['action']) {
  /*---- Update product quantities in the cart ----
  */
  case 'update_product':
    if (isset($_POST['products_id'])) {
      for ($i = 0, $n=sizeof($_POST['products_id']); $i < $n; $i++) {   
        if (!(in_array($_POST['products_id'][$i], (is_array($_POST['cart_delete']) ? $_POST['cart_delete'] : array()))) && $_POST['cart_quantity'][$i] > 1 ) {
          if (isset($_POST['id'][$_POST['products_id'][$i]])) {
            foreach($_POST['id'][$_POST['products_id'][$i]] as $option => $value) {
              if (ldProductIsDownload ($_POST['products_id'][$i], $option, $value)) {
                $_POST['cart_quantity'][$i] = 1;
                $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'][$i])), 'caution');
                break;
              }
            }
          } 
        }
      }
    }
  break;
  /*---- Add a product to cart ----
  **
  ** If a product is being added to the cart (with a quantity greater than 0) and that product includes attributes (the $_POST['id'] array
  ** is set), then if either that product is already in the cart -OR- if the quantity to be added is greater than 1,
  ** check each of the attributes being added to see if there is a download/virtual product amongst them.  If so,
  ** don't allow the duplicate download/virtual product to be added to the cart ... or just add 1 if this is the original add.
  */
  case 'add_product':
//-bof-v1.1.1c
    if (isset($_POST['products_id']) && $_POST['cart_quantity'] > 0 && isset($_POST['id']) && is_array($_POST['id'])) {
      $the_ids = $_POST['id'];
      foreach($_POST['id'] as $option => $value) {
        if (ldProductIsDownload ($_POST['products_id'], $option, $value)) {
          if ($_SESSION['cart']->in_cart(zen_get_uprid($_POST['products_id'], $the_ids))) {
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            zen_redirect(zen_href_link($goto, zen_get_all_get_params($parameters)));
            
          } elseif ($_POST['cart_quantity'] > 1) {
            $_POST['cart_quantity'] = 1;
            $messageStack->add_session('header', sprintf(ERROR_MAXIMUM_DOWNLOADS, zen_get_products_name($_POST['products_id'])), 'caution');
            
          }
          break;
        }
      }
    }
//-eof-v1.1.1c
  break;
}

function ldProductIsDownload ($products_id, $options_id, $options_value_id) {
  global $db, $zco_notifier;
  if (zen_get_products_virtual($products_id)) return true;
  
  $sql = "SELECT count(*) as count
          FROM " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
          WHERE pa.products_id = " . (int)$products_id . "
          AND   pa.options_id = " . (int)$options_id . "
          AND   pa.options_values_id = " . (int)$options_value_id . "
          AND   pa.products_attributes_id = pad.products_attributes_id";
  $sql_result = $db->Execute($sql);

  $zco_notifier->notify('LD_CHECK', array ('products_id' => $products_id, 'options_id' => $options_id, 'options_value_id' => $options_value_id, 'is_download' => $sql_result->fields['count']));
  return ($sql_result->fields['count'] > 0) ? true : false;
}

Using index.php?main_page=product_info&products_id=133, I add "quantity = 1" to the cart (English/PDF) and go back to add another "quantity=1" (English/PDF) and receive the message "The quantity for Multiple Downloads was adjusted in your cart. Your cart can hold at most one copy of each customization for a downloadable/virtual product.". I can add "quantity = 1" of the Spanish/PDF version.

I'm perplexed as to why your installation isn't experiencing the same behavior.:huh:

22 Oct 2013, 1:49 PM
#14
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

And we have a winner!

Using that code it works properly on Single Download, Multiple Download and Triple Download, tossed that in for giggles and grins, and now works in v1.3.9h, v1.5, v1.5.1, as well as the up and coming v1.5.2 and v1.6

Excellent job and thanks for the assist ...

Now I just have to fun the weird bug this tripped on a code fix that I did from my original code that tells me we doth have a potential bug in some re-writes I am working on in the shopping cart class ... but that is new code and nothing you did wrong, just helped to trigger a bizzaro error that I will need the guys to help me sort through my madness ... :cool:

Thanks again for the excellent code and hope nobody can come along and break it ...

22 Oct 2013, 2:13 PM
#15
lat9 avatar

lat9

Administrator

Join Date:
Sep 2009
Location:
Stuart, FL
Posts:
14,097
Plugin Contributions:
56

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Nobody else, that is! Thanks for the update that it's working, now. I'll get this packaged up to the Plugins.

22 Oct 2013, 2:21 PM
#16
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

I appreciate you taking the time to work through this so that even I cannot break things ... yet ... a definite asset to the community ... :cool:

22 Oct 2013, 3:23 PM
#17
divavocals avatar

divavocals

Totally Zenned

Join Date:
Jan 2007
Location:
Los Angeles, California, United States
Posts:
10,011
Plugin Contributions:
3

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

I have been sitting back watching two of the smartest women in this community working it out!!! AWESOME!!! Now that the dust has settled I can update my store..

Thanks for the hard work ladies!!!

22 Oct 2013, 4:04 PM
#18
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

I had the easy part ... breaking stuff ... :cool:

22 Oct 2013, 5:59 PM
#19
divavocals avatar

divavocals

Totally Zenned

Join Date:
Jan 2007
Location:
Los Angeles, California, United States
Posts:
10,011
Plugin Contributions:
3

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Ajeh:

I had the easy part ... breaking stuff ... :cool:

That is the fun part!!:laugh:

22 Oct 2013, 6:04 PM
#20
ajeh avatar

ajeh

Oba-san

Join Date:
Sep 2003
Location:
Ohio
Posts:
62,757
Plugin Contributions:
1

Re: Limit Quantities for Downloads and Virtual Products [Support Thread]

Yes ... it is ... :P