Search code examples
prestashop-1.7shipping-methodprestashop-modules

Prestashop shipping costs cleared after order confirmation


I'm on Prestashop 1.7.6. I made a simple test module for adding a custom carrier and manage it programmatically.

Everything works well during checkout: I see new carrier with the correct cost, if I select it the total of cart is correct! (the shipping cost is added).

After choosing the payment method and confirming the order (and I'm redirected to order confirmation page), the shipping costs disappear: is always free shipping!

I do not understand why..

I report the code of this test:

<?php
if (!defined('_PS_VERSION_')) {
    exit;
}

class TxShipping extends CarrierModule
{
    const PREFIX = 'tx_';
    public $id_carrier;

    private $loopCount = 0;
    private $shipCost = 0;

    protected $_hooks = array(
        'actionCarrierUpdate',
        'displayOrderConfirmation',
    );

    protected $_carriers = array(
        //"Public carrier name" => "technical name",
        'My new carrier' => 'txshipping',
    );

    public function __construct()
    {
        $this->name = 'txshipping';
        $this->tab = 'shipping_logistics';
        $this->version = '1.0.0';
        $this->author = 'Gerry';
        $this->need_instance = 0;
        $this->ps_versions_compliancy = [
            'min' => '1.7.1.0',
            'max' => _PS_VERSION_
        ];
        $this->bootstrap = true;

        parent::__construct();

        $this->displayName = $this->l('Tx Shipping');
        $this->description = $this->l('manage shipping costs');

        $this->confirmUninstall = $this->l('Are you sure you want to uninstall?');

        if (!Configuration::get('TXSHIPPING_NAME')) {
            $this->warning = $this->l('No name provided');
        }
    }

    public function getTemplate($area, $file)
    {
        return 'views/templates/' . $area . '/' . $file;
    }

    //-------------------------------------------------
    // Hooks
    //-------------------------------------------------
    public function hookActionCarrierUpdate($params)
    {
        if ($params['carrier']->id_reference == Configuration::get(self::PREFIX . 'fcd_reference')) {
            Configuration::updateValue(self::PREFIX . 'fcd', $params['carrier']->id);
        }
    }

    public function getOrderShippingCost($params = null, $shipping_cost = 0) {
        $curPage = $this->context->controller->php_self;

        /* using test on which page is running cause the following code is always executed (even if is loading home page!?)
           I don't understand why */
        if ($curPage == "order") {
            $this->loopCount++; // attempt for not to run the same code over and over.. but it doesn't work very well

            if ($this->loopCount == 1) {
                $this->shipCost = 77;
                /*                
                $address = new Address($params->id_address_delivery);
                $cap = $address->postcode;
                $curID = $this->id_carrier; */
            }
            return floatval($this->shipCost);

        } elseif ($curPage == "order-confirmation") {
            $test = 76; // for simple test
            return floatval($test);

        } else {
            if ($curPage != "pagenotfound") {
                $this->loopCount = 0;
                $this->shipCost = 0;
            }
        }
    }

    public function getOrderShippingCostExternal($params){
        //return 999; costi spedizione
        return $this->getOrderShippingCost($params, 0);
    }

    //-------------------------------------------------
    // Setup
    //-------------------------------------------------
    public function install()
    {
        if (parent::install()) {
            foreach ($this->_hooks as $hook) {
                if (!$this->registerHook($hook)) {
                    return false;
                }
            }

            if (!$this->createCarriers()) {
                return false;
            }

            return true;
        }
        return false;
    }

    public function uninstall()
    {
        if (parent::uninstall()) {
            foreach ($this->_hooks as $hook) {
                if (!$this->unregisterHook($hook)) {
                    return false;
                }
            }

            if (!$this->deleteCarriers()) {
                return false;
            }

            return true;
        }
        return false;
    }

    //-------------------------------------------------
    // Funzioni private
    //-------------------------------------------------
    protected function createCarriers()
    {
        foreach ($this->_carriers as $key => $value) {
            //Create own carrier
            $carrier = new Carrier();
            $carrier->name = $key;
            $carrier->id_tax_rules_group = 0;
            $carrier->active = 1;
            $carrier->deleted = 0;
            foreach (Language::getLanguages(true) as $language)
                $carrier->delay[(int)$language['id_lang']] = 'Delay [1-2 days]';
            $carrier->shipping_handling = false;
            $carrier->range_behavior = 0;
            $carrier->is_module = true;
            $carrier->shipping_external = true;
            $carrier->external_module_name = $this->name;
            $carrier->need_range = true;

            if ($carrier->add()) {
                $groups = Group::getGroups(true);
                foreach ($groups as $group) {
                    Db::getInstance()->autoExecute(_DB_PREFIX_ . 'carrier_group', array(
                        'id_carrier' => (int) $carrier->id,
                        'id_group' => (int) $group['id_group']
                    ), 'INSERT');
                }

                $rangePrice = new RangePrice();
                $rangePrice->id_carrier = $carrier->id;
                $rangePrice->delimiter1 = '0';
                $rangePrice->delimiter2 = '1000000';
                $rangePrice->add();

                $rangeWeight = new RangeWeight();
                $rangeWeight->id_carrier = $carrier->id;
                $rangeWeight->delimiter1 = '0';
                $rangeWeight->delimiter2 = '1000000';
                $rangeWeight->add();

                $zones = Zone::getZones(true);
                foreach ($zones as $z) {
                    Db::getInstance()->autoExecute(_DB_PREFIX_ . 'carrier_zone',
                        array('id_carrier' => (int) $carrier->id, 'id_zone' => (int) $z['id_zone']), 'INSERT');
                    Db::getInstance()->autoExecuteWithNullValues(_DB_PREFIX_ . 'delivery',
                        array('id_carrier' => $carrier->id, 'id_range_price' => (int) $rangePrice->id, 'id_range_weight' => NULL, 'id_zone' => (int) $z['id_zone'], 'price' => '0'), 'INSERT');
                    Db::getInstance()->autoExecuteWithNullValues(_DB_PREFIX_ . 'delivery',
                        array('id_carrier' => $carrier->id, 'id_range_price' => NULL, 'id_range_weight' => (int) $rangeWeight->id, 'id_zone' => (int) $z['id_zone'], 'price' => '0'), 'INSERT');
                }

                copy(dirname(__FILE__) . '/views/img/carrier.jpg', _PS_SHIP_IMG_DIR_ . '/' . (int) $carrier->id . '.jpg');
                Configuration::updateValue(self::PREFIX . $value, $carrier->id);
                Configuration::updateValue(self::PREFIX . $value . '_reference', $carrier->id);
            }
        }

        return true;
    }

    protected function deleteCarriers()
    {
        foreach ($this->_carriers as $value) {
            $tmp_carrier_id = Configuration::get(self::PREFIX . $value);
            $carrier = new Carrier($tmp_carrier_id);
            $carrier->delete();
        }
        return true;
    }
}

Solution

  • Im my opinion it has something to do with your $curPage

    I'd go for this if instead:

    if ($this->context->controller instanceof CartController || $this->context->controller instanceof OrderController) {

    I don't understand this part of code:

    } elseif ($curPage == "order-confirmation") {
    

    why would you do something different on real order-confirmation page where order is already placed?