Jump to content

How to know how many product combinations in a product?


NicePack

Recommended Posts

Hi, I would edit product-list.tpl to change in wich product prices I show the {l s='From'} string and I need to know how many attribute combinations has a product.

 

The thing is that if a product has combinationsNumber > 1, I show {l s='From'} before my price value. But if it has 1 or less combinations i don't show it.

 

Actually my code only looks if there is a combination like this:

{if isset($product.id_product_attribute)}
	{l s='From'}
{/if}
{if !$priceDisplay}{convertPrice price=$product.price}{else}{convertPrice price=$product.price_tax_exc}{/if}

But I would know how to check an specific number of combinations.

 

Thanks for any help! ^^

 

EDIT with solution:

 

Let's make a short explanation of this post for people who might need something similar.

 

I need to get the number of products combinations in the categories lists of my website to decide if I put a 'From' string before prices (for products with combinations of diferent prices) or not (for products with only 1 combination and only one price).

 

Problem is that product-list.tpl (the file that shows the list of products per category) seem not to be prepared to know the number of combinations of a product. Then you need to do this:

 

Edit file classes/Category.php and replace the first block (line 660) by this other SQL query where you get the number of combinations of a product as nb_attributes variable:

$sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, COUNT(DISTINCT pa.`id_product_attribute`) AS nb_attributes, MAX(product_attribute_shop.id_product_attribute) id_product_attribute, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, pl.`description`, pl.`description_short`, pl.`available_now`,
					pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, MAX(image_shop.`id_image`) id_image,
					il.`legend`, m.`name` AS manufacturer_name, cl.`name` AS category_default,
					DATEDIFF(product_shop.`date_add`, DATE_SUB(NOW(),
					INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).'
						DAY)) > 0 AS new, product_shop.price AS orderprice
				FROM `'._DB_PREFIX_.'category_product` cp
				LEFT JOIN `'._DB_PREFIX_.'product` p
					ON p.`id_product` = cp.`id_product`
				'.Shop::addSqlAssociation('product', 'p').'
				LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa
				ON (p.`id_product` = pa.`id_product`)
				'.Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1').'
				'.Product::sqlStock('p', 'product_attribute_shop', false, $context->shop).'
				LEFT JOIN `'._DB_PREFIX_.'category_lang` cl
					ON (product_shop.`id_category_default` = cl.`id_category`
					AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')
				LEFT JOIN `'._DB_PREFIX_.'product_lang` pl
					ON (p.`id_product` = pl.`id_product`
					AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').')
				LEFT JOIN `'._DB_PREFIX_.'image` i
					ON (i.`id_product` = p.`id_product`)'.
				Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
				LEFT JOIN `'._DB_PREFIX_.'image_lang` il
					ON (image_shop.`id_image` = il.`id_image`
					AND il.`id_lang` = '.(int)$id_lang.')
				LEFT JOIN `'._DB_PREFIX_.'manufacturer` m
					ON m.`id_manufacturer` = p.`id_manufacturer`
				WHERE product_shop.`id_shop` = '.(int)$context->shop->id.'
					AND cp.`id_category` = '.(int)$this->id
					.($active ? ' AND product_shop.`active` = 1' : '')
					.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')
					.($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : '')
					.' GROUP BY product_shop.id_product'; 

Then, to make this affect to categories edit too modules/blocklayered/blocklayered.php, line 1988 and replace this:

SELECT
				p.*,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'

by this:

SELECT
				p.*,COUNT(DISTINCT pa.`id_product_attribute`) AS nb_attributes,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'

Now you have your $product.nb_attributes variable accessible in product-list.tpl! Edit product-list.tpl and go near line 132 where is showing prices and offer prices and change:

{if isset($product.id_product_attribute)}

by

{if isset($product.id_product_attribute) && isset($product.nb_attributes) && $product.nb_attributes > 1}

And thats all!

 

Thanks again to Eolia and FullCircles for given help ^^

Edited by NicePack (see edit history)
  • Like 1
Link to comment
Share on other sites

 

Try just changing it to:

{if isset($product.id_product_attribute) && isset($combinations) && count($combinations) > 1}

Hey thanks for the response! But didn't worked :( Is it possible that variable $combinations doesn't exist? I doesn't enter the statement either isset($combinations) && count($combinations) > 1 or isset($combinations) && count($combinations) > 0 and happens with all products.

 

Thx for helping anyway!

Link to comment
Share on other sites

If it didn't exist, the From text would be missing from all the products, as it's checking to see if the variable exists as part of it

 

That means that perhaps there's always more than one combination.. might be a quirk of how you've got the product attributes set up

 

If inside that, you put this:

<!--
DATA HERE
{print_r($combinations)}
-->

It will print out a list of whatever is stored inside that variable, but inside html comments, so it won't affect your live site. If you right click and view the source of the page, you'll find the data hidden in there

 

Added a line that you could search by to find it easier, just search for DATA HERE using ctrl-f or your operating system equivalent

 

Should let you know what's inside that and if you paste that here, might help debug the problem

Edited by FullCircles (see edit history)
Link to comment
Share on other sites

If inside that, you put this:

<!--
DATA HERE
{print_r($combinations)}
-->

Tried this but I got always that $combinations is "1" and this is not true I have products with only 1 size combination and other with 4 sizes. What $combinations variables would be referring?

 

 

All combinations are stored in js on the front office, so:

 

<script>
$(document).ready(function(){
    var nb = combinations.length;
    alert(nb);
});
</script>

 

Sorry but dont understand this, should I put this on my product-list.tpl? How I make an if statement with nb value then? I don't know how to mix language sintaxis in a same file :blush:

Link to comment
Share on other sites

Yes you can paste it in your tpl.

<script>
$(document).ready(function(){
    var nb = combinations.length;
    if(nb >1 )
      $("#foo").show();
});
</script> 

Then create a div to insert your from condition as:

 

<div id="foo" style="display:none">{l s='From'}</div>

Link to comment
Share on other sites

Yes you can paste it in your tpl.

<script>
$(document).ready(function(){
    var nb = combinations.length;
    if(nb >1 )
      $("#foo").show();
});
</script> 

Then create a div to insert your from condition as:

 

<div id="foo" style="display:none">{l s='From'}</div>

Definitely it seems that I don't have any "combinations" variable available to read from my product-list.tpl. I've put your script but browser's console says that: ReferenceError: combinations is not defined. So I think that it can't read combinations.length :(

 

Arg, didn't though it was that hard to read how many attribute combinations has one product. Anyway thanks for your patience guys, I'll keep investigating.

Link to comment
Share on other sites

Even better:

<script>
$(document).ready(function(){
    var nb = combinations.length;
    if(nb >1 ) {
      $("#foo span").text(nb);
	  $("#foo").show();
	}
});
</script>
<div id="foo" style="display:none">{l s='This product has'} <span id="nb_of"></span> {l s='combinations'}</div>
Link to comment
Share on other sites

 

Even better:

<script>
$(document).ready(function(){
    var nb = combinations.length;
    if(nb >1 ) {
      $("#foo span").text(nb);
	  $("#foo").show();
	}
});
</script>
<div id="foo" style="display:none">{l s='This product has'} <span id="nb_of"></span> {l s='combinations'}</div>

Ok, now I see, seems that I can only read combinations inside product.tpl. I'm working on product-list.tpl to choose if I put a  {l s='From'} before prices in the product list pages. Now I supos that the ight question is: Is not possible to know if a product has combinations in the product-list.tpl?

Link to comment
Share on other sites

No with this method, combinations are sent only on the product page.

One solution:

 

In CategoryController comment this block:

	/*	Hook::exec('actionProductListOverride', array(
			'nbProducts' => &$this->nbProducts,
			'catProducts' => &$this->cat_products,
			'hookExecuted' => &$hookExecuted,
		));
*/

in classes/Category.php replace the first block (line 660) by

		$sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, COUNT(DISTINCT pa.`id_product_attribute`) AS nb_attributes, MAX(product_attribute_shop.id_product_attribute) id_product_attribute, product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, pl.`description`, pl.`description_short`, pl.`available_now`,
					pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, MAX(image_shop.`id_image`) id_image,
					il.`legend`, m.`name` AS manufacturer_name, cl.`name` AS category_default,
					DATEDIFF(product_shop.`date_add`, DATE_SUB(NOW(),
					INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).'
						DAY)) > 0 AS new, product_shop.price AS orderprice
				FROM `'._DB_PREFIX_.'category_product` cp
				LEFT JOIN `'._DB_PREFIX_.'product` p
					ON p.`id_product` = cp.`id_product`
				'.Shop::addSqlAssociation('product', 'p').'
				LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa
				ON (p.`id_product` = pa.`id_product`)
				'.Shop::addSqlAssociation('product_attribute', 'pa', false, 'product_attribute_shop.`default_on` = 1').'
				'.Product::sqlStock('p', 'product_attribute_shop', false, $context->shop).'
				LEFT JOIN `'._DB_PREFIX_.'category_lang` cl
					ON (product_shop.`id_category_default` = cl.`id_category`
					AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')
				LEFT JOIN `'._DB_PREFIX_.'product_lang` pl
					ON (p.`id_product` = pl.`id_product`
					AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').')
				LEFT JOIN `'._DB_PREFIX_.'image` i
					ON (i.`id_product` = p.`id_product`)'.
				Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'
				LEFT JOIN `'._DB_PREFIX_.'image_lang` il
					ON (image_shop.`id_image` = il.`id_image`
					AND il.`id_lang` = '.(int)$id_lang.')
				LEFT JOIN `'._DB_PREFIX_.'manufacturer` m
					ON m.`id_manufacturer` = p.`id_manufacturer`
				WHERE product_shop.`id_shop` = '.(int)$context->shop->id.'
					AND cp.`id_category` = '.(int)$this->id
					.($active ? ' AND product_shop.`active` = 1' : '')
					.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')
					.($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : '')
					.' GROUP BY product_shop.id_product'; 

and in your product_list.tpl you have (for each product) the number of combination, with, by example line 108:

This product has {$product.nb_attributes} attributes.
Edited by Eolia (see edit history)
Link to comment
Share on other sites

No thanks ?... ok, The next time it is $ 100

 

Bye.

Sorry Eolia! Had a crazy busy day yesterday :(

 

I've tried your proposed solution and indeed it gives me acces to count nb_attributes (or combinations) from product-list.tpl but seems I should not comment the CategoryController block since if I do that for some reason I loose all products in my Categories. Only can see the ones in Home in the Featured Products module.

 

What does this comment disable exactly? Maybe I have some changes in my website that affects this comment (I'm using PS 1.6.0.7 by the way).

 

Its curious because if I don't comment this I can't print the nb_attributes only on products in Featured Products module as if I couldn't access it from any category that's not Home category.

 

Anyway don't doub I apreciate a lot your efforts! I'm aware that this shouldn't be an easy question/request :/

Link to comment
Share on other sites

Ok,, i accept your apologize...
The pb comes from the blocklayered module that interact with the category class (it's a very bad idea from Prestashop, but...)
So you must add a new element to the request in this module.
 
Line 1988 in blocklayered.php (in modules/blocklayered) replace
			SELECT
				p.*,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'

by

			SELECT
				p.*,COUNT(DISTINCT pa.`id_product_attribute`) AS nb_attributes,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'

and uncomment the block in the categoryController

Link to comment
Share on other sites

 

Ok,, i accept your apologize...
The pb comes from the blocklayered module that interact with the category class (it's a very bad idea from Prestashop, but...)
So you must add a new element to the request in this module.
 
Line 1988 in blocklayered.php (in modules/blocklayered) replace
			SELECT
				p.*,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'

by

			SELECT
				p.*,COUNT(DISTINCT pa.`id_product_attribute`) AS nb_attributes,
				'.($alias_where == 'p' ? '' : 'product_shop.*,' ).'

and uncomment the block in the categoryController

 

Oh My fucking God Eolia it worked! May be God or Zinedine Zidane bless you.

 

Now I have a meeting but when arrive at home again i'll post a resume for anyone who need something similar and mark post as solved. Please don't close it yet.

Link to comment
Share on other sites

  • 1 year later...

This solution works except it shows all possible number of attributes.

Is there a way to show only the number of attributes that are in stock only?

 

Reference this url:

http://redhotbreaks.com/12-football?live_configurator_token=9220cfe7321854900688374334dfd5fb&id_shop=1&id_employee=1&theme=theme9&theme_font=

 

 

The 2nd product "2015 Panini Immaculate Football Full Case PYT" shows that it has 32 teams available, but when you click on the product and click on the dropdown, there are only 26 teams available for purchase.

 

I'd like to have it so as each team from the product gets purchased, the available number of teams on the product list page updates with the correct inventory.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...