We create the module "New mail" for Magento (part 1)

  • Tutorial

Table of contents


  1. Create a New Mail module for Magento (Part 1), where we add a new delivery method to Magento
  2. We create the “New Mail” module for Magento (part 2) , where we teach Magento to store and synchronize the warehouse database with New Mail


I have already been asked by more than one person to write a module for the most popular freight carrier of Ukraine, Novaya Pochta. This is not for one hour, so the hands did not reach. But recently, I thought that if the idea is in demand, then why not do something useful for the community, namely:
1. free module "New mail" with open source code for Magento;
2. An article in several parts with a detailed description of the process.

This article is aimed at newcomers to Magento, but it may be interesting for experienced developers as well. All sources can be found on GitHub: github.com/alexkuk/Ak_NovaPoshta , they are supplemented during development.

So, let's start with the statement of the problem. The module should perform the following functions:
1. add a new delivery method in Magento;
2. method settings should allow you to set different delivery costs for different total package weights (as in the Table Rates delivery method);
3. store and synchronize the warehouse base with New Mail;
4. display New Mail depots in a convenient form for choosing at the Shipping Method step of placing an order, by default display only depots in the user's city;
5. Add the ability to track the package in the user panel.

Recently, the New Mail API also allows you to create and print TTNs, but, with your permission, I will leave this functionality for later. In addition, with respect to clause 2, the API also provides facilities for calculating shipping costs. While I prefer a simpler and more stable option, which will allow the store owner to independently determine the cost of delivery, depending on the total weight of the order. This is due to the fact that the seller is not always able to accurately determine the weight of each product, and the shipping cost set through the API may not play to the benefit of the seller. Leave the cost calculation through the API for later.

Add a new delivery method


So, create a new module and add a new delivery method. I will work with Magento CE 1.7.0.2. The module is called Ak_NovaPoshta. A lot of articles have already been written about the structure of modules in Magento, so I’ll omit this point.

It is worth noting that Magento operates on two entities, when we talk about the delivery method, these are shipping carrier (carrier) and shipping methods (shipping methods that are provided by the carrier). In our case, the carrier is New Mail, we will use New Mail depots as methods.

To add carrier, you need to do three things:
1. add the settings fields of our carrier in the system.xml module;

2. Add default settings values, as well as a link to the carrier model class, in the module config.xml:
01UAnovaposhta/carrier_novaPoshtaНовая ПочтаЭтот способ доставки на текущий момент не доступен. Если вы желаете, чтобы мы доставили заказ Новой Почтой, обратитесь к менеджеру интернет-магазина.

3. Add a class model to our carrier.
The carrier model class inherits from Mage_Shipping_Model_Carrier_Abstract and implements Mage_Shipping_Model_Carrier_Interface. Some useful methods are already defined in Mage_Shipping_Model_Carrier_Abstract, such as the getConfigData ($ field) method for retrieving configuration values. In our class, we define the main method collectRates (Mage_Shipping_Model_Rate_Request $ request), which will return the available delivery methods:
    public function collectRates(Mage_Shipping_Model_Rate_Request $request)
    {
       if (!$this->getConfigFlag('active')) {
           return false;
       }
       /** @var $result Mage_Shipping_Model_Rate_Result */
       $result = Mage::getModel('shipping/rate_result');
       $shippingPrice = 1.00; // dummy price
       $warehouseId = 1; // dummy warehouse ID
       $warehouseName = 'Склад №1'; // dummy warehouse name
       /** @var $method Mage_Shipping_Model_Rate_Result_Method */
       $method = Mage::getModel('shipping/rate_result_method');
       $method->setCarrier($this->_code)
           ->setCarrierTitle($this->getConfigData('name'))
           ->setMethod('warehouse_' . $warehouseId)
           ->setMethodTitle($warehouseName)
           ->setPrice($shippingPrice)
           ->setCost($shippingPrice);
       $result->append($method);
       return $result;
    }

Until we have implemented the synchronization of warehouses, we will use one delivery method for an example - Warehouse No. 1. Inside the collectRates () method, create an instance of Mage_Shipping_Model_Rate_Result, and using the Mage_Shipping_Model_Rate_Result :: append () method add Mage_Shipping_Model_Rate_Result_Method instances to it.

Finally, we rewrite the parent method isTrackingAvailable:
    public function isTrackingAvailable()
    {
       return true;
    }

At this stage, our delivery method can already be used, but as you can see, the shipping cost will always be 1.00.

Add the configuration of the shipping cost


The next step is to add a configuration option for linking the total weight of the order and the shipping cost. As a result, I want to get this form:



To do this, add the weight_price field to the system.xml of our module:
novaposhta/config_field_weightPriceadminhtml/system_config_backend_serialized_array110111

Backend model is a model that converts the value of a field before saving to the database. In this case, we will use the ready-made model Mage_Adminhtml_Model_System_Config_Backend_Serialized_Array. Frontend model is not a model at all, but a block responsible for representing the field. We will add our Ak_NovaPoshta_Block_Config_Field_WeightPrice block:
class Ak_NovaPoshta_Block_Config_Field_WeightPrice extends Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract
{
    public function __construct()
    {
       $this->addColumn('weight', array(
           'label' => Mage::helper('novaposhta')->__('Weight upper limit'),
           'style' => 'width:120px',
       ));
       $this->addColumn('price', array(
           'label' => Mage::helper('novaposhta')->__('Price'),
           'style' => 'width:120px',
       ));
       $this->_addAfter = false;
       $this->_addButtonLabel = Mage::helper('novaposhta')->__('Add rate');
       parent::__construct();
    }
}

As you can see, the abstract Mage_Adminhtml_Block_System_Config_Form_Field_Array_Abstract does all the work for us, it remains for us to configure the columns and buttons.

The configuration field is ready, now let's move on to its use, namely, finding the cost of delivery of the order. To do this, add the following methods to the carrier class:
    /**
    * @return array
    */
    protected function _getWeightPriceMap()
    {
       $weightPriceMap = $this->getConfigData('weight_price');
       if (empty($weightPriceMap)) {
           return array();
       }
       return unserialize($weightPriceMap);
    }
    /**
    * @param $packageWeight
    *
    * @return float
    */
    protected function _getDeliveryPriceByWeight($packageWeight)
    {
       $weightPriceMap = $this->_getWeightPriceMap();
       $resultingPrice = 0.00;
       if (empty($weightPriceMap)) {
           return $resultingPrice;
       }
       $minimumWeight = 1000000000;
       foreach ($weightPriceMap as $weightPrice) {
           if ($packageWeight <= $weightPrice['weight'] && $weightPrice['weight'] <= $minimumWeight) {
               $minimumWeight = $weightPrice['weight'];
               $resultingPrice = $weightPrice['price'];
           }
       }
       return $resultingPrice;
    }

and in the collectRates method we replace
$shippingPrice = 1.00

to a more real
$shippingPrice = $this->_getDeliveryPriceByWeight($request->getPackageWeight());


Done.



In the next part I’ll deal with the synchronization of the warehouse database with the New Mail API. Thanks for attention!

Also popular now: