Skip to content

Instantly share code, notes, and snippets.

@KarmCraft
Last active May 1, 2023 14:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KarmCraft/3464785a5aa35ef0d594d5eee573ce61 to your computer and use it in GitHub Desktop.
Save KarmCraft/3464785a5aa35ef0d594d5eee573ce61 to your computer and use it in GitHub Desktop.
Prestashop 1.7.X - Better Catalog Price Rule calculation per product
<?php
/**
* Fixes the specific Price calculation in default PrestaShop installation.
* Makes sure that the highest Discount in Catalog Price Rules is applied to the product
* indipendently if the discount is by % or by amount
*
* If you have set up discounts on the customer group level, you may remove these and recreate
* them as a Catalog Price Rule. This way the fix also applies to these cases.
*
* Instruction: Upload to override/classes/, delete var/cache/prod/class_index.php and empty the cache
*
* @author KarmaEDV https://www.karmaedv.ch https://www.karmcraft.com
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
class SpecificPrice extends SpecificPriceCore
{
public static function getSpecificPrice(
$id_product,
$id_shop,
$id_currency,
$id_country,
$id_group,
$quantity,
$id_product_attribute = null,
$id_customer = 0,
$id_cart = 0,
$real_quantity = 0
) {
if (!SpecificPrice::isFeatureActive()) {
return [];
}
/*
* The date is not taken into account for the cache, but this is for the better because it keeps the consistency
* for the whole script.
* The price must not change between the top and the bottom of the page
*/
if (!self::couldHaveSpecificPrice($id_product)) {
return [];
}
if (static::$psQtyDiscountOnCombination === null) {
static::$psQtyDiscountOnCombination = Configuration::get('PS_QTY_DISCOUNT_ON_COMBINATION');
// no need to compute the key the first time the function is called, we know the cache has not
// been computed yet
$key = null;
} else {
$key = self::computeKey(
$id_product,
$id_shop,
$id_currency,
$id_country,
$id_group,
$quantity,
$id_product_attribute,
$id_customer,
$id_cart,
$real_quantity
);
}
if (!array_key_exists($key, self::$_specificPriceCache)) {
$price_query = '
SELECT price FROM `' . _DB_PREFIX_ . 'product`
WHERE `id_product` = ' . $id_product;
$price_orig = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($price_query);
$query_extra = self::computeExtraConditions($id_product, $id_product_attribute, $id_customer, $id_cart);
if ($key === null) {
// compute the key after calling computeExtraConditions as it initializes some useful cache
$key = self::computeKey(
$id_product,
$id_shop,
$id_currency,
$id_country,
$id_group,
$quantity,
$id_product_attribute,
$id_customer,
$id_cart,
$real_quantity
);
}
$query = '
SELECT *, ' . SpecificPrice::_getScoreQuery($id_product, $id_shop, $id_currency, $id_country, $id_group, $id_customer) . '
FROM `' . _DB_PREFIX_ . 'specific_price`
WHERE
`id_shop` ' . self::formatIntInQuery(0, $id_shop) . ' AND
`id_currency` ' . self::formatIntInQuery(0, $id_currency) . ' AND
`id_country` ' . self::formatIntInQuery(0, $id_country) . ' AND
`id_group` ' . self::formatIntInQuery(0, $id_group) . ' ' . $query_extra . '
AND IF(`from_quantity` > 1, `from_quantity`, 0) <= ';
$query .= (static::$psQtyDiscountOnCombination || !$id_cart || !$real_quantity) ? (int) $quantity : max(1, (int) $real_quantity);
$query .= " ORDER BY CASE WHEN reduction_type = 'amount' THEN (reduction / " . $price_orig . ") ELSE reduction END DESC";
self::$_specificPriceCache[$key] = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
}
return self::$_specificPriceCache[$key];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment