Jump to content

Shipping cost preview not showing fix


Recommended Posts

I have found a bug for which I made a dirty fix, I think PS people should chime in and do a proper fix.

My shop version
How to reproduce:
Create one shipping method by weight with all zones available and with prices.
add someting to cart, you should see a field: "Total shipping" in cart which shows you the cheapest available shipping cost.
Now create another method by weight where your default country is enabeled, but choose some zone that it is not enabeled ie africa.
now if you use a prestashop shipping estimator set the country in FO estimator to some african country, the shipping cost is no longer populated in the "Total shipping" field.
The solution: change the function "getDeliveryOptionList" in classes/cart.php
line 2125

 if (is_null($best_price) || $price_with_tax < $best_price) {
                        $best_price = $price_with_tax;
                        $best_price_carrier = $id_carrier;


 if ((is_null($best_price) || $price_with_tax < $best_price) && $price_without_tax != 0 ){
                        $best_price = $price_with_tax;
                        $best_price_carrier = $id_carrier;

This part of the code registers the best price and best price carrier, but it does not differentiate wether the zone is enabeled or not, if a particular zone is disabeled it reads the best price as zero, my code disables zero values.


This has a setback because free shipping is now not displayed either, but t works for me sice I dont do free sipping at the moment.

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

I hink I have found the problem. This function is in classes/carrier.php

  public static function getCarriers($id_lang, $active = false, $delete = false, $id_zone = false, $ids_group = null, $modules_filters = self::PS_CARRIERS_ONLY)
        // Filter by groups and no groups => return empty array
        if ($ids_group && (!is_array($ids_group) || !count($ids_group))) {
            return array();

        $sql = '
		SELECT c.*, cl.delay
		FROM `'._DB_PREFIX_.'carrier` c
		LEFT JOIN `'._DB_PREFIX_.'carrier_lang` cl ON (c.`id_carrier` = cl.`id_carrier` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')
		LEFT JOIN `'._DB_PREFIX_.'carrier_zone` cz ON (cz.`id_carrier` = c.`id_carrier`)'.
        ($id_zone ? 'LEFT JOIN `'._DB_PREFIX_.'zone` z ON (z.`id_zone` = '.(int)$id_zone.')' : '').'
		'.Shop::addSqlAssociation('carrier', 'c').'
		WHERE c.`deleted` = '.($delete ? '1' : '0');
        if ($active) {
            $sql .= ' AND c.`active` = 1 ';
        if ($id_zone) {
            $sql .= ' AND cz.`id_zone` = '.(int)$id_zone.' AND z.`active` = 1 ';
        if ($ids_group) {
            $sql .= ' AND EXISTS (SELECT 1 FROM '._DB_PREFIX_.'carrier_group
									WHERE '._DB_PREFIX_.'carrier_group.id_carrier = c.id_carrier
									AND id_group IN ('.implode(',', array_map('intval', $ids_group)).')) ';

        switch ($modules_filters) {
            case 1 :
                $sql .= ' AND c.is_module = 0 ';
            case 2 :
                $sql .= ' AND c.is_module = 1 ';
            case 3 :
                $sql .= ' AND c.is_module = 1 AND c.need_range = 1 ';
            case 4 :
                $sql .= ' AND (c.is_module = 0 OR c.need_range = 1) ';
        $sql .= ' GROUP BY c.`id_carrier` ORDER BY c.`position` ASC';

        $cache_id = 'Carrier::getCarriers_'.md5($sql);
        if (!Cache::isStored($cache_id)) {
            $carriers = Db::getInstance()->executeS($sql);

This is supposed to return carier info about all active carriers that are vailable for a certain zone


I used print_r to see the result of this sql quiery and even when the zone id is set, it returns shipping methods that are not available for selected zone.

Can anyone spot the error please?

Link to comment
Share on other sites

Ok I think I have nailed it, the database query above is OK.


The prestashop finds shipping costs in very complicated way. The most importand thing with my issue was that it makes two loops, one for finding available shipping methods for each package and another to find prices aln all other relevant stuff for the packages.


The problem is the first loop is made based on delivey address, if that does not exist then PS default country.

But the other loop is made with the country stored in cookie


So you get two different results from each loop and thats what causes the error.

Now I have added a cookie check for the first loop.


So if you have problem shipping cost not showing or shows default country cost, even the cookie is different, then here is the code you need to change:


vor ver in classes/carrier.php line 1310 find:

        } else {
            $country = new Country($ps_country_default);
            $id_zone = $country->id_zone;

Replace with:

       } else {
		   if (isset(Context::getContext()->cookie->id_country)) {
                $country = new Country(Context::getContext()->cookie->id_country);	
		    } else {	
                $country = new Country($ps_country_default);
            $id_zone = $country->id_zone;
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...