Note : Cet article s’applique uniquement aux versions de Magento inférieures à la 1.6

Sur une version 1.5 de Magento j’ai été confronté au comportement d’erreur suivant :

Pour un panier comportant un bon de réduction.
Les frais de ports devant être offerts à partir de X euros.

  • les frais de ports n’étaient pas calculés correctement dans le checkout lors de l’affichage des méthodes de livraisons
  • Les frais de ports étaient calculés correctement dans l’estimation des frais de port du panier
  • Les frais de ports étaient correct dans le résumé de la commande.
  • Si l’adresse de livraison étaient différente de l’adresse de livraison , le calcul était correct.

Après analyse du code, il s’avère que les frais de ports ne sont pas recalculés si on conserve la même adresse de livraison.
Voici comment corriger cela.

Il faut surcharger la fonction saveBilling du fichier app/code/core/Mage/Checkout/Model/Type/Onepage.php.
Pour cela, nous pouvons au choix faire un override du modèle (meilleure solution ) ou déplacer ce fichier dans le codePool local.

    public function saveBilling($data, $customerAddressId)
    {
        if (empty($data)) {
            return array('error' => -1, 'message' => $this->_helper->__('Invalid data.'));
        }
 
        $address = $this->getQuote()->getBillingAddress();
        /* @var $addressForm Mage_Customer_Model_Form */
        $addressForm = Mage::getModel('customer/form');
        $addressForm->setFormCode('customer_address_edit')
            ->setEntityType('customer_address')
            ->setIsAjaxRequest(Mage::app()->getRequest()->isAjax());
 
        if (!empty($customerAddressId)) {
            $customerAddress = Mage::getModel('customer/address')->load($customerAddressId);
            if ($customerAddress->getId()) {
                if ($customerAddress->getCustomerId() != $this->getQuote()->getCustomerId()) {
                    return array('error' => 1,
                        'message' => $this->_helper->__('Customer Address is not valid.')
                    );
                }
 
                $address->importCustomerAddress($customerAddress)->setSaveInAddressBook(0);
                $addressForm->setEntity($address);
                $addressErrors  = $addressForm->validateData($address->getData());
                if ($addressErrors !== true) {
                    return array('error' => 1, 'message' => $addressErrors);
                }
            }
        } else {
            $addressForm->setEntity($address);
            // emulate request object
            $addressData    = $addressForm->extractData($addressForm->prepareRequest($data));
            $addressErrors  = $addressForm->validateData($addressData);
            if ($addressErrors !== true) {
                return array('error' => 1, 'message' => $addressErrors);
            }
            $addressForm->compactData($addressData);
 
            // Additional form data, not fetched by extractData (as it fetches only attributes)
            $address->setSaveInAddressBook(empty($data['save_in_address_book']) ? 0 : 1);
        }
 
        // validate billing address
        if (($validateRes = $address->validate()) !== true) {
            return array('error' => 1, 'message' => $validateRes);
        }
 
        $address->implodeStreetAddress();
 
        if (true !== ($result = $this->_validateCustomerData($data))) {
            return $result;
        }
 
        if (!$this->getQuote()->getCustomerId() && self::METHOD_REGISTER == $this->getQuote()->getCheckoutMethod()) {
            if ($this->_customerEmailExists($address->getEmail(), Mage::app()->getWebsite()->getId())) {
                return array('error' => 1, 'message' => $this->_customerEmailExistsMessage);
            }
        }
 
        if (!$this->getQuote()->isVirtual()) {
            /**
             * Billing address using otions
             */
            $usingCase = isset($data['use_for_shipping']) ? (int)$data['use_for_shipping'] : 0;
 
            switch($usingCase) {
                case 0:
                    $shipping = $this->getQuote()->getShippingAddress();
                    $shipping->setSameAsBilling(0);
                    break;
                case 1:
                    $billing = clone $address;
                    $billing->unsAddressId()->unsAddressType();
                    $shipping = $this->getQuote()->getShippingAddress();
                    $shippingMethod = $shipping->getShippingMethod();
                    $shipping->addData($billing->getData())
                        ->setSameAsBilling(1)
                        ->setSaveInAddressBook(0)
                        ->setShippingMethod($shippingMethod)
                        ->setCollectShippingRates(true);
                    $this->getCheckout()->setStepData('shipping', 'complete', true);
                    break;
            }
        }
 
        //Recalcul des shipping Rates
        $this->getQuote()->collectTotals();
        $this->getQuote()->setTotalsCollectedFlag(false);
        $this->getQuote()->getShippingAddress()->setCollectShippingRates(true)->save();
        //Fin du recalcul
 
        $this->getQuote()->collectTotals();
        $this->getQuote()->save();
 
        $this->getCheckout()
            ->setStepData('billing', 'allow', true)
            ->setStepData('billing', 'complete', true)
            ->setStepData('shipping', 'allow', true);
 
        return array();
    }

Cette surcharge rajoute en fin de traitement des instructions pour forcer la récupération des frais de livraisons.
Une fois celle-ci en place, les frais de port seront bien recalculés avec les bonnes valeurs 🙂