How to fix Cart Rules in PrestaShop 1.6.0.7 to 1.6.1.1

I recently had a support for a PrestaShop 1.6.0.11 where the cart rule was not taken into account in the order page, no matter what, the carrier price was still the same (instead of a free shipping).

I found out it came from the CartRule class of PrestaShop, more precisely from the country restriction.

Explanation

In classes/CartRule.php, in function getCustomerCartRules() you will find this piece of code :

if ($cart_rule['country_restriction']) {
    $countries = Db::getInstance()->ExecuteS('
        SELECT `id_country`
        FROM `'._DB_PREFIX_.'address`
        WHERE `id_customer` = '.(int)$id_customer.'
        AND `deleted` = 0'
    );

    if (is_array($countries) && count($countries)) {
        foreach ($countries as $country) {
            $id_cart_rule = (bool)Db::getInstance()->getValue('
                SELECT crc.id_cart_rule
                FROM '._DB_PREFIX_.'cart_rule_country crc
                WHERE crc.id_cart_rule = '.(int)$cart_rule['id_cart_rule'].'
                AND crc.id_country = '.(int)$country['id_country']);
            if (!$id_cart_rule) {
                unset($result[$key]);
            }
        }
    }
}

Long story short, PrestaShop gets all the customer's addresses and loop on them. If only ONE address is not listed in the country restriction (selected countries).

Then all your cart rule will be erased in

if (!$id_cart_rule) {
    unset($result[$key]);
}

Which means it does not even care about the delivery address...
Just : if customer has an address in an unselected country then do not return the cart rule.

Fix

In the getCustomerCartRules() function, the last parameter given is the cart. Lucky for us, we can just use this cart to fetch the delivery address then check if id_country of the address matches the one PrestaShop is dealing with in the loop.

IF the id_country that PrestaShop is checking IS NOT the id_country of the cart address THEN continue.

if ($cart_rule['country_restriction'])
{
    $address = null;
    if (Validate::isLoadedObject($cart)) {
        $address = new Address((int)$cart->id_address_delivery);
    }

    $countries = Db::getInstance()->ExecuteS('
        SELECT `id_country`
        FROM `'._DB_PREFIX_.'address`
        WHERE `id_customer` = '.(int)$id_customer.'
        AND `deleted` = 0'
    );

    if (is_array($countries) && count($countries)) {
        foreach($countries as $country)
        {
            if (Validate::isLoadedObject($address) && $address->id_country != $country['id_country']) {
                continue;
            }

            $id_cart_rule = (bool)Db::getInstance()->getValue('
                SELECT crc.id_cart_rule
                FROM '._DB_PREFIX_.'cart_rule_country crc
                WHERE crc.id_cart_rule = '.(int)$cart_rule['id_cart_rule'].'
                AND crc.id_country = '.(int)$country['id_country']);

            if (!$id_cart_rule)
                unset($result[$key]);
        }
    }
}

Can be convenient if you are not going to update to PrestaShop 1.6.1.2 or more any soon.



Blog Comments powered by Disqus.