Table of contents
- Create a new mail module for Magento (Part 1), where we add a new delivery method to Magento
- We create the “New Mail” module for Magento (part 2) , where we teach Magento to store and synchronize the warehouse base with New Mail
Not one person has already asked me to write a module for the most popular cargo carrier of Ukraine, “New Mail”. This is not the case for one hour, so the hands did not reach. But recently I thought that if an idea is needed, then why not do something useful for the community, namely:
1. free module "New mail" open source for Magento;
2. article in several parts with a detailed description of the process.
The article is aimed at beginners in Magento, but, perhaps, it will be interesting and experienced developers. All sources can be found on GitHub:
github.com/alexkuk/Ak_NovaPoshta , they are supplemented in the course of development.
')
So, let's start with the problem statement. The module should perform the following functions:
1. add a new delivery method to Magento;
2. method settings should allow you to specify different shipping costs for different total weight of the package (as in the Table Rates delivery method);
3. store and synchronize the warehouse base with New Mail;
4. output the New Mail warehouses in a convenient way for selection at the Shipping Method step of placing the order, by default, display only the warehouses in the user's city;
5. Add the ability to track the parcel to the user panel.
Recently, the New Mail API also allows you to create and print TTH, but, with your permission, I will leave this functionality for later. In addition, regarding clause 2, the API also provides the means to calculate shipping costs. For now, I prefer a simpler and more stable option that 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 work for the seller’s benefit. 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 module structure in Magento, so I’ll omit this moment.
It should be noted that Magento operates with two entities, when we talk about the delivery method, it is the shipping carrier and shipping methods (shipping methods provided by the carrier). In our case, the carrier is New Mail, we will use the warehouses of New Mail as methods.
To add a carrier, you need to do three things:
1. add our carrier's configuration fields to the system.xml module;
2. add the default settings values, as well as a link to the carrier model class, in the module config.xml:
<config> … <default> <carriers> <novaposhta> <active>0</active> <sallowspecific>1</sallowspecific> <specificcountry>UA</specificcountry> <model>novaposhta/carrier_novaPoshta</model> <title> </title> <specificerrmsg> . , , -.</specificerrmsg> </novaposhta> </carriers> </default> … </config>
3. Add a class model for our carrier.
The carrier model class is inherited from Mage_Shipping_Model_Carrier_Abstract and implements Mage_Shipping_Model_Carrier_Interface. Mage_Shipping_Model_Carrier_Abstract has already defined some useful methods, such as the getConfigData ($ field) method for retrieving configuration values. In our class, we define the main collectRates method (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; } $result = Mage::getModel('shipping/rate_result'); $shippingPrice = 1.00;
While we have not implemented warehouse synchronization, 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 use the Mage_Shipping_Model_Rate_Result :: append () method to add instances of Mage_Shipping_Model_Rate_Result_Method 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 cost of delivery will always be 1.00.
Add shipping cost configuration
The next step is to add a configuration option for linking the total order weight and shipping cost. In the end, I want to get this form:

To do this, add the weight_price field in the system.xml of our module:
… <weight_price translate="label"> <label>Shipping price</label> <frontend_model>novaposhta/config_field_weightPrice</frontend_model> <backend_model>adminhtml/system_config_backend_serialized_array</backend_model> <sort_order>110</sort_order> <show_in_default>1</show_in_default> <show_in_website>1</show_in_website> <show_in_store>1</show_in_store> </weight_price> …
A backend model is a model that converts a field value before saving to the base. In this case, we will use the finished model Mage_Adminhtml_Model_System_Config_Backend_Serialized_Array. The frontend model is not a model at all, but a unit responsible for the field representation. 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, we just have to set up the columns and buttons.
The configuration field is ready, now let's move on to its use, namely, to find the delivery cost of the order. To do this, add the following methods to the carrier class:
protected function _getWeightPriceMap() { $weightPriceMap = $this->getConfigData('weight_price'); if (empty($weightPriceMap)) { return array(); } return unserialize($weightPriceMap); } 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
on more real
$shippingPrice = $this->_getDeliveryPriceByWeight($request->getPackageWeight());
Is done

In the next part, I will synchronize the warehouse base with the New Mail API. Thanks for attention!