Our goal is to display available product combinations and their prices on a product page. For example, our store proposes some loyalty discount program, and we should show all product prices in a proper way. The following solution will fit for you in case you have a variety of product combinations and a set of user group discount rules.
Among them are: Distributors, Regular customers, Special customers, etc.
There are several methods how to apply a discount in PrestaShop:
Group discount — you can set up a discount in % for a certain User Group:
Catalog Price Rules — allow setting up a discount depending on a product quantity, user group, combination, etc. Moreover it’s possible to set up a discount for each product separately (Specific Price):
Combination Impact on price — set price for every combination:
Moreover there are some types of discount rules based on the cart items (Cart Rules), but we won’t consider this case in this post.
By default a price is displayed only for the selected combination. After a product attribute is changed, a new price is calculated according to the applied discount rules. So we just need to understand the process of these calculations and apply it to all possible combinations.
PrestaShop Modules
Take your store to the next level with PrestaShop modules from BelVG
Visit the storeLet’s take a look at what happens when you choose a certain combination, and how PrestaShop calculates a new product price.
All described code is taken from the default-bootstrap/js/product.js file.
Selected combination is passed in the URI anchor, so a JavaScript global variable is in our disposal.
Let’s take a look at the Combinations array. The following JavaScript object is filled in the product.tpl template by the ProductController class.
This object contains price (Combination Impact on price) and specific_price (Catalog Price Rules) elements.
Also we have access to global price variables (ProductPrice, productPriceTaxIncluded, etc.) that affect the final product price with applied group discounts and country based taxes (also calculated in the ProductController).
So now we are able to display prices with Catalog Price Rules and Impact on Price discounts applied.
Here is a custom template with combinations and applied discounts.
To achieve the same result you need to develop a custom module with template for calculations according to the available Combinations based on the ProductController. But what if we want to create Price Rule for a purchase of 10+ or even 100+ products? You expect Combinations to contain additional information about all available discounts. Yes, this could be rather helpful. But it is not the way PrestaShop is built.
Partner With Us
Let's discuss how to grow your business. Get a Free Quote.If you add a PriceRule with the From quantity parameter and reload a page, you will see that a new Volume Discounts table. And in case you increase the Quantity JavaScript will parse this table and update the current price. Such option does not suit us at all. The data that we need is not passed into JavaScript global variables, we don’t need the Volume Price table as well.
JavaScript adds anchor to the page URL after you select a combination. Thereafter the script calculates the final price with the applied discount and updates value on the page.
PrestaShop Development
Take your online store to the next level with BelVG PrestaShop Development
Visit the pageSo the following solution can suit us:
Let’s create a hook in our module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public function hookProductFooter($params) { $product = new Product(Tools::getValue('id_product'), true, $cookie->id_lang); $grid_quantity_discounts = $this->getQuantityDiscounts( $product, $this->context->shop->id, $this->context->currency->id, $this->context->country->id, (int)Group::getCurrent()->id ); $smarty->assign(array('grid_quantity_discounts' => $grid_quantity_discounts)); return $this->display(__FILE__, 'our-template.tpl'); } |
We are going to use 2 native methods from the ProductController: getQuantityDiscounts() and formatQuantityDiscounts():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public function getQuantityDiscounts($product, $id_shop, $id_currency, $id_country, $id_group) { $quantity_discounts = SpecificPrice::getQuantityDiscounts($product->id, $id_shop, $id_currency, $id_country, $id_group, null, true, (int)$this->context->customer->id); foreach ($quantity_discounts as &$quantity_discount) { if ($quantity_discount['id_product_attribute']) { $combination = new Combination((int)$quantity_discount['id_product_attribute']); $attributes = $combination->getAttributesName((int)$this->context->language->id); foreach ($attributes as $attribute) { $quantity_discount['attributes'] = $attribute['name'] . ' - '; } $quantity_discount['attributes'] = rtrim($quantity_discount['attributes'], ' - '); } if ((int)$quantity_discount['id_currency'] == 0 && $quantity_discount['reduction_type'] == 'amount') { $quantity_discount['reduction'] = Tools::convertPriceFull($quantity_discount['reduction'], null, Context::getContext()->currency); } } $tax = (float)$product->getTaxesRate(new Address((int)$this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); $ecotax_rate = (float)Tax::getProductEcotaxRate($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $ecotax_tax_amount = Tools::ps_round($this->product->ecotax, 2); if (Product::$_taxCalculationMethod == PS_TAX_INC && (int)Configuration::get('PS_TAX')) { $ecotax_tax_amount = Tools::ps_round($ecotax_tax_amount * (1 + $ecotax_rate / 100), 2); } $product_price = $product->getPrice(Product::$_taxCalculationMethod == PS_TAX_INC, false); $address = new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); return $this->formatQuantityDiscounts($quantity_discounts, $product_price, (float)$tax, $ecotax_tax_amount); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
protected function formatQuantityDiscounts($specific_prices, $price, $tax_rate, $ecotax_amount) { foreach ($specific_prices as $key => &$row) { $row['quantity'] = &$row['from_quantity']; if ($row['price'] >= 0) { // The price may be directly set $cur_price = (!$row['reduction_tax'] ? $row['price'] : $row['price'] * (1 + $tax_rate / 100)) + (float)$ecotax_amount; if ($row['reduction_type'] == 'amount') { $cur_price -= ($row['reduction_tax'] ? $row['reduction'] : $row['reduction'] / (1 + $tax_rate / 100)); $row['reduction_with_tax'] = $row['reduction_tax'] ? $row['reduction'] : $row['reduction'] / (1 + $tax_rate / 100); } else { $cur_price *= 1 - $row['reduction']; } $row['real_value'] = $price > 0 ? $price - $cur_price : $cur_price; } else { if ($row['reduction_type'] == 'amount') { if (Product::$_taxCalculationMethod == PS_TAX_INC) { $row['real_value'] = $row['reduction_tax'] == 1 ? $row['reduction'] : $row['reduction'] * (1 + $tax_rate / 100); } else { $row['real_value'] = $row['reduction_tax'] == 0 ? $row['reduction'] : $row['reduction'] / (1 + $tax_rate / 100); } $row['reduction_with_tax'] = $row['reduction_tax'] ? $row['reduction'] : $row['reduction'] + ($row['reduction'] * $tax_rate) / 100; } else { $row['real_value'] = $row['reduction'] * 100; } } $row['nextQuantity'] = (isset($specific_prices[$key + 1]) ? (int)$specific_prices[$key + 1]['from_quantity'] : -1); } return $specific_prices; } |
Now we can create a JavaScript variable in the template:
1 2 3 |
<script type="text/javascript"> var ag_grid_quantity_discounts = {$grid_quantity_discounts|@json_encode}; </script> |
Finally we have all necessary data in order to display “from quantity” discounts properly.
PrestaShop Support & Maintenance
Take your online store to the next level with BelVG PrestaShop Support & Maintenance
Visit the page
@pascal, Dima described customization of the 3rd party module, you can contact our support team via [email protected] for the details
Hello,
Is there a way to download the module you write with this template ?
Thanks