<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NemoPS &#187; combinations</title>
	<atom:link href="https://nemops.com/tag/combinations/feed/" rel="self" type="application/rss+xml" />
	<link>https://nemops.com</link>
	<description>Prestashop Tutorials, Modules and More!</description>
	<lastBuildDate>Wed, 05 Dec 2018 13:25:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.35</generator>
	<item>
		<title>Adding text for back-orderable Combinations in PrestaShop</title>
		<link>https://nemops.com/adding-text-for-back-orderable-combinations-in-prestashop/</link>
		<comments>https://nemops.com/adding-text-for-back-orderable-combinations-in-prestashop/#comments</comments>
		<pubDate>Wed, 10 Aug 2016 09:33:08 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Tips n Tricks]]></category>
		<category><![CDATA[combinations]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[products]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=2837</guid>
		<description><![CDATA[<p>In this flash tip we will see how to display an explanatory text for combinations which you have no stock for, but still want to allow the purchase of. PrestaShop Version used: 1.6.1.5 The background Do you allow back ordering products? If so, you might have noticed PrestaShop tends to be confusing on combinations. In [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://nemops.com/adding-text-for-back-orderable-combinations-in-prestashop/">Adding text for back-orderable Combinations in PrestaShop</a> appeared first on <a rel="nofollow" href="https://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>In this flash tip we will see how to display an explanatory text for combinations which you have no stock for, but still want to allow the purchase of.</p>
<p><span id="more-2837"></span></p>
<ul>
<li>PrestaShop Version used: 1.6.1.5</li>
</ul>
<h2>The background</h2>
<p>Do you allow back ordering products? If so, you might have noticed PrestaShop tends to be confusing on combinations. In the default template, when a combination is available and has stock, it displays the classic <strong>X items in stock</strong> message. However, if you select a combination that has currently zero stock, even if available for order, it displays nothing. Forum users have reported customers being confused by this, so let&#8217;s see how to fix it, and give our customers more feedback!</p>
<div class="separator"></div>
<h2>The translatable string</h2>
<p>Unless you run a single language shop, you will need the text we are going to display to be translatable. Therefore, we will take advantage of PrestaShop&#8217;s AddJsDefL method to add a javascript variable that can easily be translated from the back office. Open up your <strong>product.tpl</strong> file, located in the theme folder. At the very end of it, add the following:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{addJsDefL name='onBackOrderText'}{l s='On backorder' js=1}{/addJsDefL}
</pre>
<p><strong>What does it do?</strong> It takes any content between tags and assigns it to the variable with a given name. There is a manual method as well, but this is the one that better complies to PrestaShop standards. If you want to know more about this and other functions, you can refer to my <strong><a href="http://nemops.com/prestashop-functions-1/#.V6rx7_n5jmg" target="_blank" title="Essential PrestaShop functions">Essential PrestaShop functions</a></strong> series.</p>
<div class="separator"></div>
<h2>Editing product.js</h2>
<p>Now that we have a string to play with, we have to make it work as we want. Open up <strong>product.js</strong>, located in the theme folder <em>/js/</em>. Please notice yours might be different if you do not use the default template. Locate the following at around line 630:</p>
<pre class="brush: jscript; title: ; notranslate">
		if (allowBuyWhenOutOfStock &amp;&amp; !selectedCombination['unavailable'] &amp;&amp; productAvailableForOrder)
		{
			$('#add_to_cart:hidden').fadeIn(600);

			if (stock_management &amp;&amp; availableLaterValue != '')
			{
				$('#availability_value').addClass('label-warning').text(availableLaterValue).show('slow');
				$('#availability_statut:hidden').show('slow');
			}
			else 
				$('#availability_statut:visible').hide('slow');
				
		}
</pre>
<p>The last part, in the else, is the one responsible for not displaying anything. We could simply comment it out, but if you try it, you will notice it says the product is available in other variants only. What to do then? Let&#8217;s modify it as follows:</p>
<pre class="brush: jscript; title: ; notranslate">
		if (allowBuyWhenOutOfStock &amp;&amp; !selectedCombination['unavailable'] &amp;&amp; productAvailableForOrder)
		{
			$('#add_to_cart:hidden').fadeIn(600);

			if (stock_management &amp;&amp; availableLaterValue != '')
			{
				$('#availability_value').addClass('label-warning').text(availableLaterValue).show('slow');
				$('#availability_statut:hidden').show('slow');
			}
			else {
				$('#availability_value').addClass('label-warning').text(onBackOrderText).show('slow');
				// $('#availability_statut:visible').hide('slow');
			}
				
		}
</pre>
<p>We just added brackets to the else statement, then copied the label-warning part from above, and used our text variable instead. Save and refresh, then try reloading the page with the combination selected, as well as switching between that and others. You will notice the text behaves as expected now!</p>
<p>The post <a rel="nofollow" href="https://nemops.com/adding-text-for-back-orderable-combinations-in-prestashop/">Adding text for back-orderable Combinations in PrestaShop</a> appeared first on <a rel="nofollow" href="https://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://nemops.com/adding-text-for-back-orderable-combinations-in-prestashop/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enable Combinations for Virtual Products in Prestashop 1.6/1.5</title>
		<link>https://nemops.com/prestashop-virtual-products-combinations/</link>
		<comments>https://nemops.com/prestashop-virtual-products-combinations/#comments</comments>
		<pubDate>Tue, 14 Jan 2014 09:51:03 +0000</pubDate>
		<dc:creator><![CDATA[Nemo]]></dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[combinations]]></category>
		<category><![CDATA[prestashop]]></category>
		<category><![CDATA[virtual products]]></category>

		<guid isPermaLink="false">http://nemops.com/?p=1767</guid>
		<description><![CDATA[<p>Prestashop 1.4 used to let you create combinations for downloadable items. It was the same file for every combinations, but we could use them, at least. This is no longer possible with Prestashop 1.5 and 1.6&#8217;s virtual products, so let&#8217;s see how to turn this feature back! The problem: You cannot use combinations with a [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://nemops.com/prestashop-virtual-products-combinations/">Enable Combinations for Virtual Products in Prestashop 1.6/1.5</a> appeared first on <a rel="nofollow" href="https://nemops.com">NemoPS</a>.</p>
]]></description>
				<content:encoded><![CDATA[<p>Prestashop 1.4 used to let you create combinations for downloadable items. It was the same file for every combinations, but we could use them, at least. This is no longer possible with Prestashop 1.5 and 1.6&#8217;s virtual products, so let&#8217;s see how to turn this feature back!</p>
<p><span id="more-1767"></span></p>
<h2>The problem: You cannot use combinations with a virtual product</h2>
<p>If you ever tried to add attribute combinations to a virtual product, or turn into virtual a normal one that already had them, you might have run into this message. In the worst case, you just upgraded from 1.4 and discovered your products didn&#8217;t have the previous files attached anymore, if they had combinations. Despite having to re-bind all the downloadable files in the latter case, we can re-enable combinations for virtual products in Prestashop 1.5 using some overrides:</p>
<ul>
<li>AdminProductsController</li>
<li>combinations.tpl (back office template file)</li>
<li>virtualproduct.tpl</li>
</ul>
<p>We will simply disable a couple of checks Prestashop does, which turn off combinations if the product is virtual, and vice-versa.</p>
<div class="separator"></div>
<h2>The AdminProductsController Override</h2>
<p>First of all, let&#8217;s disable the virtual product check in the product&#8217;s back office. Create a new file in <em>override/controllers/admin</em> and call it <strong>AdminProductsController.php</strong>. Add the following to begin with, inside php tags of course:</p>
<pre class="brush: php; title: ; notranslate">
class AdminProductsController extends AdminProductsControllerCore
{
}
</pre>
<p>At this point, we need to extend and modify the method named <strong>initFormAttributes</strong>. Therefore, open up the original AdminProductsController.php (<em>controllers/admin</em>), copy initFormAttributes from there (about line 3628 in Prestashop 1.5.6), and paste the whole function inside the new override.</p>
<p>Then, locate the following:</p>
<pre class="brush: php; title: ; notranslate">
if ($this-&gt;product_exists_in_shop)
			{
				if ($product-&gt;is_virtual)
				{
					$data-&gt;assign('product', $product);
					$this-&gt;displayWarning($this-&gt;l('A virtual product cannot have combinations.'));
				}
				else
				{
					$attribute_js = array();
					$attributes = Attribute::getAttributes($this-&gt;context-&gt;language-&gt;id, true);
					foreach ($attributes as $k =&gt; $attribute)
						$attribute_js[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name'];
					$currency = $this-&gt;context-&gt;currency;
					$data-&gt;assign('attributeJs', $attribute_js);
					$data-&gt;assign('attributes_groups', AttributeGroup::getAttributesGroups($this-&gt;context-&gt;language-&gt;id));

					$data-&gt;assign('currency', $currency);

					$images = Image::getImages($this-&gt;context-&gt;language-&gt;id, $product-&gt;id);

					$data-&gt;assign('tax_exclude_option', Tax::excludeTaxeOption());
					$data-&gt;assign('ps_weight_unit', Configuration::get('PS_WEIGHT_UNIT'));

					$data-&gt;assign('ps_use_ecotax', Configuration::get('PS_USE_ECOTAX'));
					$data-&gt;assign('field_value_unity', $this-&gt;getFieldValue($product, 'unity'));

					$data-&gt;assign('reasons', $reasons = StockMvtReason::getStockMvtReasons($this-&gt;context-&gt;language-&gt;id));
					$data-&gt;assign('ps_stock_mvt_reason_default', $ps_stock_mvt_reason_default = Configuration::get('PS_STOCK_MVT_REASON_DEFAULT'));
					$data-&gt;assign('minimal_quantity', $this-&gt;getFieldValue($product, 'minimal_quantity') ? $this-&gt;getFieldValue($product, 'minimal_quantity') : 1);
					$data-&gt;assign('available_date', ($this-&gt;getFieldValue($product, 'available_date') != 0) ? stripslashes(htmlentities($this-&gt;getFieldValue($product, 'available_date'), $this-&gt;context-&gt;language-&gt;id)) : '0000-00-00');

					$i = 0;
					$data-&gt;assign('imageType', ImageType::getByNameNType('small_default', 'products'));
					$data-&gt;assign('imageWidth', (isset($image_type['width']) ? (int)($image_type['width']) : 64) + 25);
					foreach ($images as $k =&gt; $image)
					{
						$images[$k]['obj'] = new Image($image['id_image']);
						++$i;
					}
					$data-&gt;assign('images', $images);

					$data-&gt;assign($this-&gt;tpl_form_vars);
					$data-&gt;assign(array(
						'list' =&gt; $this-&gt;renderListAttributes($product, $currency),
						'product' =&gt; $product,
						'id_category' =&gt; $product-&gt;getDefaultCategory(),
						'token_generator' =&gt; Tools::getAdminTokenLite('AdminAttributeGenerator'),
						'combination_exists' =&gt; (Shop::isFeatureActive() &amp;&amp; (Shop::getContextShopGroup()-&gt;share_stock) &amp;&amp; count(AttributeGroup::getAttributesGroups($this-&gt;context-&gt;language-&gt;id)) &gt; 0 &amp;&amp; $product-&gt;hasAttributes())
					));
				}
			}
			else
				$this-&gt;displayWarning($this-&gt;l('You must save the product in this shop before adding combinations.'));	
</pre>
<p>Can you see where it reads <strong>if ($product->is_virtual)</strong>? Get rid of this if/else, so it looks like this:</p>
<pre class="brush: php; title: ; notranslate">
			if ($this-&gt;product_exists_in_shop)
			{
				// removed virtual product restriction
				$attribute_js = array();
				$attributes = Attribute::getAttributes($this-&gt;context-&gt;language-&gt;id, true);
				foreach ($attributes as $k =&gt; $attribute)
					$attribute_js[$attribute['id_attribute_group']][$attribute['id_attribute']] = $attribute['name'];
				$currency = $this-&gt;context-&gt;currency;
				$data-&gt;assign('attributeJs', $attribute_js);
				$data-&gt;assign('attributes_groups', AttributeGroup::getAttributesGroups($this-&gt;context-&gt;language-&gt;id));

				$data-&gt;assign('currency', $currency);

				$images = Image::getImages($this-&gt;context-&gt;language-&gt;id, $product-&gt;id);

				$data-&gt;assign('tax_exclude_option', Tax::excludeTaxeOption());
				$data-&gt;assign('ps_weight_unit', Configuration::get('PS_WEIGHT_UNIT'));

				$data-&gt;assign('ps_use_ecotax', Configuration::get('PS_USE_ECOTAX'));
				$data-&gt;assign('field_value_unity', $this-&gt;getFieldValue($product, 'unity'));

				$data-&gt;assign('reasons', $reasons = StockMvtReason::getStockMvtReasons($this-&gt;context-&gt;language-&gt;id));
				$data-&gt;assign('ps_stock_mvt_reason_default', $ps_stock_mvt_reason_default = Configuration::get('PS_STOCK_MVT_REASON_DEFAULT'));
				$data-&gt;assign('minimal_quantity', $this-&gt;getFieldValue($product, 'minimal_quantity') ? $this-&gt;getFieldValue($product, 'minimal_quantity') : 1);
				$data-&gt;assign('available_date', ($this-&gt;getFieldValue($product, 'available_date') != 0) ? stripslashes(htmlentities($this-&gt;getFieldValue($product, 'available_date'), $this-&gt;context-&gt;language-&gt;id)) : '0000-00-00');

				$i = 0;
				$type = ImageType::getByNameNType('%', 'products', 'height');
				if (isset($type['name']))
					$data-&gt;assign('imageType', $type['name']);
				else
					$data-&gt;assign('imageType', 'small_default');
				$data-&gt;assign('imageWidth', (isset($image_type['width']) ? (int)($image_type['width']) : 64) + 25);
				foreach ($images as $k =&gt; $image)
				{
					$images[$k]['obj'] = new Image($image['id_image']);
					++$i;
				}
				$data-&gt;assign('images', $images);

				$data-&gt;assign($this-&gt;tpl_form_vars);
				$data-&gt;assign(array(
					'list' =&gt; $this-&gt;renderListAttributes($product, $currency),
					'product' =&gt; $product,
					'id_category' =&gt; $product-&gt;getDefaultCategory(),
					'token_generator' =&gt; Tools::getAdminTokenLite('AdminAttributeGenerator'),
					'combination_exists' =&gt; (Shop::isFeatureActive() &amp;&amp; (Shop::getContextShopGroup()-&gt;share_stock) &amp;&amp; count(AttributeGroup::getAttributesGroups($this-&gt;context-&gt;language-&gt;id)) &gt; 0 &amp;&amp; $product-&gt;hasAttributes())
				));
				
			}
			else
				$this-&gt;displayWarning($this-&gt;l('You must save the product in this shop before adding combinations.'));	
</pre>
<p>Save the file, go to <em>cache/</em> and delete <strong>class_index.php</strong>. Then access the product&#8217;s back office again, load a virtual product and click on the combinations tab. Nothing! At least, it&#8217;s better than the error message. We need to tackle another step.</p>
<div class="separator"></div>
<h2>Editing the attribute combinations template</h2>
<p>Inside the same folder where we placed our override, create the following structure: <em>templates/products/</em>. Then, reach the admin folder <em>themes/default/template/controllers/products</em>. Copy <strong>combinations.tpl</strong> from here into the other folder we just created.</p>
<p>At this point, open the newly cloned file, and right at the beginning we can read:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
{if isset($product-&gt;id) &amp;&amp; !$product-&gt;is_virtual}
</pre>
<p>Just get rid of <strong> &#038;&#038; !$product->is_virtual</strong>. Save and access the combinations tab again!</p>
<div class="separator"></div>
<h2>Finishing touches</h2>
<p>You can create combinations for a virtual product right away. However, if you try to convert an existing one into virtual, you will get the very same annoying message you got before. We need to hardcode a small fix in another couple of files, first: <strong>admin-products.js</strong>, which  can be found inside the <em>js</em> folder. Open it up and locate the following:</p>
<pre class="brush: jscript; title: ; notranslate">
				if (has_combinations)
				{
					$('#simple_product').attr('checked', true);
					$('#warn_virtual_combinations').show();
				}
				else
				{
					$('li.tab-row a[id*=&quot;VirtualProduct&quot;]').show().click();
					$('#is_virtual').val(1);

					tabs_manager.onLoad('VirtualProduct', function(){
						$('#is_virtual_good').attr('checked', true);
						$('#virtual_good').show();
					});

					tabs_manager.onLoad('Quantities', function(){
						$('.stockForVirtualProduct').hide();
					});

					$('li.tab-row a[id*=&quot;Shipping&quot;]').hide();

					tabs_manager.onLoad('Informations', function(){
						$('#condition').attr('disabled', true);
						$('#condition option[value=refurbished]').removeAttr('selected');
						$('#condition option[value=used]').removeAttr('selected');
					});
				}
</pre>
<p>Change it to</p>
<pre class="brush: jscript; title: ; notranslate">

					$('li.tab-row a[id*=&quot;VirtualProduct&quot;]').show().click();
					$('#is_virtual').val(1);

					tabs_manager.onLoad('VirtualProduct', function(){
						$('#is_virtual_good').attr('checked', true);
						$('#virtual_good').show();
					});

					tabs_manager.onLoad('Quantities', function(){
						$('.stockForVirtualProduct').hide();
					});

					$('li.tab-row a[id*=&quot;Shipping&quot;]').hide();

					tabs_manager.onLoad('Informations', function(){
						$('#condition').attr('disabled', true);
						$('#condition option[value=refurbished]').removeAttr('selected');
						$('#condition option[value=used]').removeAttr('selected');
					});
				
</pre>
<p>Then, once more, reach the <em>themes/default/template/controllers/products</em> folder. This time, copy <strong>virtualproduct.tpl</strong> to the same folder where we added combinations.tpl. Open it up and inspect the following snippet:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">
			{* Don't display file form if the product has combinations *}
			{if empty($product-&gt;cache_default_attribute)}
				{if $product-&gt;productDownload-&gt;id}
					&lt;input type=&quot;hidden&quot; id=&quot;virtual_product_id&quot; name=&quot;virtual_product_id&quot; value=&quot;{$product-&gt;productDownload-&gt;id}&quot; /&gt;
				{/if}
				&lt;table cellpadding=&quot;5&quot; style=&quot;float: left; margin-left: 10px;&quot;&gt;
					&lt;tr id=&quot;upload_input&quot; {if $is_file}style=&quot;display:none&quot;{/if}&gt;
						&lt;td class=&quot;col-left&quot;&gt;
							&lt;label id=&quot;virtual_product_file_label&quot; for=&quot;virtual_product_file&quot; class=&quot;t&quot;&gt;{l s='Upload a file'}&lt;/label&gt;
						&lt;/td&gt;
						&lt;td class=&quot;col-right&quot;&gt;
							&lt;input type=&quot;file&quot; id=&quot;virtual_product_file&quot; name=&quot;virtual_product_file&quot; onchange=&quot;uploadFile();&quot; maxlength=&quot;{$upload_max_filesize}&quot; /&gt;
							&lt;p class=&quot;preference_description&quot;&gt;{l s='Your server\'s maximum file-upload size is'}:&amp;nbsp;{$upload_max_filesize} {l s='MB'}&lt;/p&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr id=&quot;upload-error&quot; style=&quot;display:none&quot;&gt;
						&lt;td colspan=2&gt;&lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr id=&quot;upload-confirmation&quot; style=&quot;display:none&quot;&gt;
						&lt;td colspan=2&gt;
							{if $up_filename}
								&lt;input type=&quot;hidden&quot; id=&quot;virtual_product_filename&quot; name=&quot;virtual_product_filename&quot; value=&quot;{$up_filename}&quot; /&gt;
							{/if}
							&lt;div class=&quot;conf&quot;&gt;
							&lt;script&gt;
								delete_this_file = '{l s='Delete this file'}';
							&lt;/script&gt;
								&lt;a class=&quot;delete_virtual_product&quot; id=&quot;delete_downloadable_product&quot; href=&quot;{$currentIndex}&amp;deleteVirtualProduct=true&amp;token={$token}&amp;id_product={$product-&gt;id}&quot; class=&quot;red&quot;&gt;
									&lt;img src=&quot;../img/admin/delete.gif&quot; alt=&quot;{l s='Delete this file'}&quot;/&gt;
								&lt;/a&gt;
							&lt;/div&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					{if $is_file}
						&lt;tr&gt;
							&lt;td class=&quot;col-left&quot;&gt;
								&lt;input type=&quot;hidden&quot; id=&quot;virtual_product_filename&quot; name=&quot;virtual_product_filename&quot; value=&quot;{$product-&gt;productDownload-&gt;filename}&quot; /&gt;
								&lt;label class=&quot;t&quot;&gt;{l s='Link to the file:'}&lt;/label&gt;
							&lt;/td&gt;
							 &lt;td class=&quot;col-right&quot;&gt;
								{$product-&gt;productDownload-&gt;getHtmlLink(false, true)}
								&lt;a href=&quot;{$currentIndex}&amp;deleteVirtualProduct=true&amp;token={$token}&amp;id_product={$product-&gt;id}&quot; class=&quot;red delete_virtual_product&quot;&gt;
									&lt;img src=&quot;../img/admin/delete.gif&quot; alt=&quot;{l s='Delete this file'}&quot;/&gt;
								&lt;/a&gt;
							&lt;/td&gt;
						&lt;/tr&gt;
					{/if}
					&lt;tr&gt;
						&lt;td class=&quot;col-left&quot;&gt;
							&lt;label for=&quot;virtual_product_name&quot; class=&quot;t&quot;&gt;{l s='Filename'}&lt;/label&gt;
						&lt;/td&gt;
						&lt;td class=&quot;col-right&quot;&gt;
							&lt;input type=&quot;text&quot; id=&quot;virtual_product_name&quot; name=&quot;virtual_product_name&quot; style=&quot;width:200px&quot; value=&quot;{$product-&gt;productDownload-&gt;display_filename|escape:'htmlall':'UTF-8'}&quot; /&gt;
							&lt;p class=&quot;preference_description&quot; name=&quot;help_box&quot;&gt;{l s='The full filename with its extension (e.g. Book.pdf)'}&lt;/p&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;
						&lt;td class=&quot;col-left&quot;&gt;
							&lt;label for=&quot;virtual_product_nb_downloable&quot; class=&quot;t&quot;&gt;{l s='Number of allowed downloads'}&lt;/label&gt;
						&lt;/td&gt;
						&lt;td class=&quot;col-right&quot;&gt;
							&lt;input type=&quot;text&quot; id=&quot;virtual_product_nb_downloable&quot; name=&quot;virtual_product_nb_downloable&quot; value=&quot;{$product-&gt;productDownload-&gt;nb_downloadable|htmlentities}&quot; class=&quot;&quot; size=&quot;6&quot; /&gt;
							&lt;p class=&quot;preference_description&quot;&gt;{l s='Number of downloads allowed per customer. (Set to 0 for unlimited downloads)'}&lt;/p&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					&lt;tr&gt;
						&lt;td class=&quot;col-left&quot;&gt;
							&lt;label for=&quot;virtual_product_expiration_date&quot; class=&quot;t&quot;&gt;{l s='Expiration date'}&lt;/label&gt;
						&lt;/td&gt;
						&lt;td class=&quot;col-right&quot;&gt;
							&lt;input class=&quot;datepicker&quot; type=&quot;text&quot; id=&quot;virtual_product_expiration_date&quot; name=&quot;virtual_product_expiration_date&quot; value=&quot;{$product-&gt;productDownload-&gt;date_expiration}&quot; size=&quot;11&quot; maxlength=&quot;10&quot; autocomplete=&quot;off&quot; /&gt; {l s='Format: YYYY-MM-DD'}
							&lt;p class=&quot;preference_description&quot;&gt;{l s='If set, the file will not be downloadable after this date. Leave blank if you do not wish to attach an expiration date.'}&lt;/p&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
						&lt;td class=&quot;col-left&quot;&gt;
							&lt;label for=&quot;virtual_product_nb_days&quot; class=&quot;t&quot;&gt;{l s='Number of days'}&lt;/label&gt;
						&lt;/td&gt;
						&lt;td class=&quot;col-right&quot;&gt;
							&lt;input type=&quot;text&quot; id=&quot;virtual_product_nb_days&quot; name=&quot;virtual_product_nb_days&quot; value=&quot;{$product-&gt;productDownload-&gt;nb_days_accessible|htmlentities}&quot; class=&quot;&quot; size=&quot;4&quot; /&gt;&lt;sup&gt; *&lt;/sup&gt;
							&lt;p class=&quot;preference_description&quot;&gt;{l s='Number of days this file can be accessed by customers'} - &lt;em&gt;({l s='Set to zero for unlimited access.'})&lt;/em&gt;&lt;/p&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					{* Feature not implemented *}
					{*&lt;tr&gt;*}
						{*&lt;td class=&quot;col-left&quot;&gt;*}
							{*&lt;label for=&quot;virtual_product_is_shareable&quot; class=&quot;t&quot;&gt;{l s='is shareable'}&lt;/label&gt;*}
						{*&lt;/td&gt;*}
						{*&lt;td class=&quot;col-right&quot;&gt;*}
							{*&lt;input type=&quot;checkbox&quot; id=&quot;virtual_product_is_shareable&quot; name=&quot;virtual_product_is_shareable&quot; value=&quot;1&quot; {if $product-&gt;productDownload-&gt;is_shareable}checked=&quot;checked&quot;{/if} /&gt;*}
							{*&lt;span class=&quot;hint&quot; name=&quot;help_box&quot; style=&quot;display:none&quot;&gt;{l s='Please specify if the file can be shared.'}&lt;/span&gt;*}
						{*&lt;/td&gt;*}
					{*&lt;/tr&gt;*}
				{else}
					&lt;div class=&quot;hint clear&quot; style=&quot;display: block;width: 70%;&quot;&gt;{l s='You cannot edit your file here because you used combinations. Please edit this file in the Combinations tab.'}&lt;/div&gt;
					&lt;br /&gt;
					{if isset($error_product_download)}{$error_product_download}{/if}
				{/if}
</pre>
<p>Change it to:</p>
<pre class="brush: php; html-script: true; title: ; notranslate">

			{if $product-&gt;productDownload-&gt;id}
				&lt;input type=&quot;hidden&quot; id=&quot;virtual_product_id&quot; name=&quot;virtual_product_id&quot; value=&quot;{$product-&gt;productDownload-&gt;id}&quot; /&gt;
			{/if}
			&lt;table cellpadding=&quot;5&quot; style=&quot;float: left; margin-left: 10px;&quot;&gt;
				&lt;tr id=&quot;upload_input&quot; {if $is_file}style=&quot;display:none&quot;{/if}&gt;
					&lt;td class=&quot;col-left&quot;&gt;
						&lt;label id=&quot;virtual_product_file_label&quot; for=&quot;virtual_product_file&quot; class=&quot;t&quot;&gt;{l s='Upload a file'}&lt;/label&gt;
					&lt;/td&gt;
					&lt;td class=&quot;col-right&quot;&gt;
						&lt;input type=&quot;file&quot; id=&quot;virtual_product_file&quot; name=&quot;virtual_product_file&quot; onchange=&quot;uploadFile();&quot; maxlength=&quot;{$upload_max_filesize}&quot; /&gt;
						&lt;p class=&quot;preference_description&quot;&gt;{l s='Your server\'s maximum file-upload size is'}:&amp;nbsp;{$upload_max_filesize} {l s='MB'}&lt;/p&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
				&lt;tr id=&quot;upload-error&quot; style=&quot;display:none&quot;&gt;
					&lt;td colspan=2&gt;&lt;/td&gt;
				&lt;/tr&gt;
				&lt;tr id=&quot;upload-confirmation&quot; style=&quot;display:none&quot;&gt;
					&lt;td colspan=2&gt;
						{if $up_filename}
							&lt;input type=&quot;hidden&quot; id=&quot;virtual_product_filename&quot; name=&quot;virtual_product_filename&quot; value=&quot;{$up_filename}&quot; /&gt;
						{/if}
						&lt;div class=&quot;conf&quot;&gt;
						&lt;script&gt;
							delete_this_file = '{l s='Delete this file'}';
						&lt;/script&gt;
							&lt;a class=&quot;delete_virtual_product&quot; id=&quot;delete_downloadable_product&quot; href=&quot;{$currentIndex}&amp;deleteVirtualProduct=true&amp;token={$token}&amp;id_product={$product-&gt;id}&quot; class=&quot;red&quot;&gt;
								&lt;img src=&quot;../img/admin/delete.gif&quot; alt=&quot;{l s='Delete this file'}&quot;/&gt;
							&lt;/a&gt;
						&lt;/div&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
				{if $is_file}
					&lt;tr&gt;
						&lt;td class=&quot;col-left&quot;&gt;
							&lt;input type=&quot;hidden&quot; id=&quot;virtual_product_filename&quot; name=&quot;virtual_product_filename&quot; value=&quot;{$product-&gt;productDownload-&gt;filename}&quot; /&gt;
							&lt;label class=&quot;t&quot;&gt;{l s='Link to the file:'}&lt;/label&gt;
						&lt;/td&gt;
						 &lt;td class=&quot;col-right&quot;&gt;
							{$product-&gt;productDownload-&gt;getHtmlLink(false, true)}
							&lt;a href=&quot;{$currentIndex}&amp;deleteVirtualProduct=true&amp;token={$token}&amp;id_product={$product-&gt;id}&quot; class=&quot;red delete_virtual_product&quot;&gt;
								&lt;img src=&quot;../img/admin/delete.gif&quot; alt=&quot;{l s='Delete this file'}&quot;/&gt;
							&lt;/a&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				{/if}
				&lt;tr&gt;
					&lt;td class=&quot;col-left&quot;&gt;
						&lt;label for=&quot;virtual_product_name&quot; class=&quot;t&quot;&gt;{l s='Filename'}&lt;/label&gt;
					&lt;/td&gt;
					&lt;td class=&quot;col-right&quot;&gt;
						&lt;input type=&quot;text&quot; id=&quot;virtual_product_name&quot; name=&quot;virtual_product_name&quot; style=&quot;width:200px&quot; value=&quot;{$product-&gt;productDownload-&gt;display_filename|escape:'htmlall':'UTF-8'}&quot; /&gt;
						&lt;p class=&quot;preference_description&quot; name=&quot;help_box&quot;&gt;{l s='The full filename with its extension (e.g. Book.pdf)'}&lt;/p&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
				&lt;tr&gt;
					&lt;td class=&quot;col-left&quot;&gt;
						&lt;label for=&quot;virtual_product_nb_downloable&quot; class=&quot;t&quot;&gt;{l s='Number of allowed downloads'}&lt;/label&gt;
					&lt;/td&gt;
					&lt;td class=&quot;col-right&quot;&gt;
						&lt;input type=&quot;text&quot; id=&quot;virtual_product_nb_downloable&quot; name=&quot;virtual_product_nb_downloable&quot; value=&quot;{$product-&gt;productDownload-&gt;nb_downloadable|htmlentities}&quot; class=&quot;&quot; size=&quot;6&quot; /&gt;
						&lt;p class=&quot;preference_description&quot;&gt;{l s='Number of downloads allowed per customer. (Set to 0 for unlimited downloads)'}&lt;/p&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
				&lt;tr&gt;
					&lt;td class=&quot;col-left&quot;&gt;
						&lt;label for=&quot;virtual_product_expiration_date&quot; class=&quot;t&quot;&gt;{l s='Expiration date'}&lt;/label&gt;
					&lt;/td&gt;
					&lt;td class=&quot;col-right&quot;&gt;
						&lt;input class=&quot;datepicker&quot; type=&quot;text&quot; id=&quot;virtual_product_expiration_date&quot; name=&quot;virtual_product_expiration_date&quot; value=&quot;{$product-&gt;productDownload-&gt;date_expiration}&quot; size=&quot;11&quot; maxlength=&quot;10&quot; autocomplete=&quot;off&quot; /&gt; {l s='Format: YYYY-MM-DD'}
						&lt;p class=&quot;preference_description&quot;&gt;{l s='If set, the file will not be downloadable after this date. Leave blank if you do not wish to attach an expiration date.'}&lt;/p&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
					&lt;td class=&quot;col-left&quot;&gt;
						&lt;label for=&quot;virtual_product_nb_days&quot; class=&quot;t&quot;&gt;{l s='Number of days'}&lt;/label&gt;
					&lt;/td&gt;
					&lt;td class=&quot;col-right&quot;&gt;
						&lt;input type=&quot;text&quot; id=&quot;virtual_product_nb_days&quot; name=&quot;virtual_product_nb_days&quot; value=&quot;{$product-&gt;productDownload-&gt;nb_days_accessible|htmlentities}&quot; class=&quot;&quot; size=&quot;4&quot; /&gt;&lt;sup&gt; *&lt;/sup&gt;
						&lt;p class=&quot;preference_description&quot;&gt;{l s='Number of days this file can be accessed by customers'} - &lt;em&gt;({l s='Set to zero for unlimited access.'})&lt;/em&gt;&lt;/p&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
				{* Feature not implemented *}
				{*&lt;tr&gt;*}
					{*&lt;td class=&quot;col-left&quot;&gt;*}
						{*&lt;label for=&quot;virtual_product_is_shareable&quot; class=&quot;t&quot;&gt;{l s='is shareable'}&lt;/label&gt;*}
					{*&lt;/td&gt;*}
					{*&lt;td class=&quot;col-right&quot;&gt;*}
						{*&lt;input type=&quot;checkbox&quot; id=&quot;virtual_product_is_shareable&quot; name=&quot;virtual_product_is_shareable&quot; value=&quot;1&quot; {if $product-&gt;productDownload-&gt;is_shareable}checked=&quot;checked&quot;{/if} /&gt;*}
						{*&lt;span class=&quot;hint&quot; name=&quot;help_box&quot; style=&quot;display:none&quot;&gt;{l s='Please specify if the file can be shared.'}&lt;/span&gt;*}
					{*&lt;/td&gt;*}
				{*&lt;/tr&gt;*}

</pre>
<p><strong>Explanation:</strong> we basically got rid of the if/else statement which was triggering the message, instead of displaying the virtual product form.</p>
<p>Save, and we are done!</p>
<h2>A note about prestashop 1.6</h2>
<p>Iclavijos, user of the Prestashop forums, found out an additional step is needed in order to make virtual products work with combinations in Prestashop 1.6, here follows his advice</p>
<p>You need to override form.tpl (controllers/admin/templates/products/helpers/form) and there, comment out line 116. Basically, this is the original code:</p>
<pre class="brush: php; title: ; notranslate">
else if (product_type == product_type_virtual)

                {

                    $('a[id*=&quot;Pack&quot;]').hide();

                    $('a[id*=&quot;Shipping&quot;]').hide();

                    $('a[id*=&quot;Combinations&quot;]').hide();

                }[
</pre>
<p>and this should be the final one:</p>
<pre class="brush: php; title: ; notranslate">
else if (product_type == product_type_virtual)

                {

                    $('a[id*=&quot;Pack&quot;]').hide();

                    $('a[id*=&quot;Shipping&quot;]').hide();

                    //$('a[id*=&quot;Combinations&quot;]').hide();

                }
</pre>
<p>Thanks for your contribution!</p>
<div class="separator"></div>
<h2>Final note</h2>
<p>Although we used overrides to ensure changes are preserved after an upgrade, remember to re-apply the admin-products.js fix, as we had to hardcode that one!.</p>
<p>The post <a rel="nofollow" href="https://nemops.com/prestashop-virtual-products-combinations/">Enable Combinations for Virtual Products in Prestashop 1.6/1.5</a> appeared first on <a rel="nofollow" href="https://nemops.com">NemoPS</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://nemops.com/prestashop-virtual-products-combinations/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
	</channel>
</rss>
