Instalacja modułu Paczkomaty InPost w Magento z nietypowym modułem koszyka

Paczkomaty InPost to bardzo popularna forma wysyłki i z pewnością większość wdrożeń Magento uwzględnia ją w projekcie. Wykonawcą modułu jest znana na rynku polskim i nie tylko firma ORBA. Nie jestem ekspertem, ale jak dla mnie moduł jest napisany bardzo dobrze i działa świetnie. W tym artykule chciałbym podzielić się kilkoma informacjami dotyczącymi uruchomienia Paczkomatów InPost z nietypowym koszykiem Magento.

W jednym z wdrożeń Magento zastosowałem moduł koszyka o nazwie Lotus Breath – One Step Checkout. Jest to całkiem niezły darmowy moduł Magento oferujący bardzo dobry jednostronny koszyk. Jednak pojawiły się problemy z uruchomieniem metody wysyłki Paczkomaty Inpost w module One Step Checkout.

Integracja modułu One Step Checkout z Paczkomaty Inpost

Aby połączyć funkcjonalności tych dwóch modułów potrzeba zmodyfikować dwa pliki w module Paczkomaty Inpost:

  1. w pliku /app/code/community/Inpost/ParcelLocker/etc/config.xml
  2.  w pliku /app/code/community/Inpost/ParcelLocker/Model/Observer/Block.php

W przypadku pliku config.xml należy go rozbudować o następujący fragment struktury danych, który zaznaczyłem na czerwono:

<?xml version="1.0"?>
<layout version="0.1.0">
    <checkout_onepage_index>
        <reference name="head">
            <!-- action method="addItem">
                <type>js</type>
                <name>inpost/jquery-1.11.3.min.js</name>
            </action>
            <action method="addItem">
                <type>js</type>
                <name>inpost/noconflict.js</name>
            </action -->
            <action method="addItem">
                <type>js</type>
                <name>inpost/checkout.js</name>
            </action>
            <action method="addItem">
                <type>js</type>
                <name>inpost/validation.js</name>
            </action>
            <action method="addCss">
                <name>css/inpost.css</name>
            </action>
        </reference>
    </checkout_onepage_index>
    <lotusbreath_onestepcheckout_index_index>
        <reference name="head">
            <!-- action method="addItem">
                <type>js</type>
                <name>inpost/jquery-1.11.3.min.js</name>
            </action>
            <action method="addItem">
                <type>js</type>
                <name>inpost/noconflict.js</name>
            </action -->
            <action method="addItem">
                <type>js</type>
                <name>inpost/checkout.js</name>
            </action>
            <action method="addItem">
                <type>js</type>
                <name>inpost/validation.js</name>
            </action>
            <action method="addCss">
                <name>css/inpost.css</name>
            </action>
        </reference>
    </lotusbreath_onestepcheckout_index_index>

    <inpost_return_index translate="label"  module="inpost_parcellocker">
        <reference name="head">
            <action method="addCss">
                <name>css/inpost.css</name>
            </action>
        </reference>
        <update handle="customer_account"/>
        <reference name="my.account.wrapper">
            <block type="inpost_parcellocker/customer_account_return" name="inpost_customer_account_return" />
        </reference>
    </inpost_return_index>
    <inpost_market_pl>
        <reference name="customer_account_navigation">
            <action method="addLink" translate="label" module="inpost_parcellocker">
                <name>inpost_returns</name>
                <path>inpost/return/index</path>
                <label>InPost - Fast Returns</label>
            </action>
        </reference>
    </inpost_market_pl>
</layout>

Dodatkowo dałem w komentarz akcję dodającą plik jQuery gdyż użyty szablon w projekcie już zaczytuje ten plik, nie ma więc potrzeby dodawać go ponownie.

Kolejne zmiany wprowadzamy w pliku Block.php:

<?php

class Inpost_ParcelLocker_Model_Observer_Block {

    const SHIPPING_METHOD_BLOCK_TYPE = 'checkout/onepage_shipping_method_available';
    const SHIPPING_METHOD_BLOCK_TYPE_LOTUS = 'lotusbreath_onestepcheckout/onepage_shipping_method_available';
    const FRONTEND_HEAD_BLOCK_TYPE = 'page/html_head';
    const BACKEND_HEAD_BLOCK_TYPE = 'adminhtml/page_head';
    const SHIPPING_METHOD_INPOST_PARCELLOCKER_DESCRIPTION = 'inpost_parcellocker/checkout_shipping_method_parcellocker_description';
    const SHIPPING_METHOD_INPOST_PARCELLOCKER_FORM = 'inpost_parcellocker/checkout_shipping_method_parcellocker_form';
    const SHIPPING_METHOD_INPOST_CROSSBORDER_DESCRIPTION = 'inpost_parcellocker/checkout_shipping_method_crossborder_description';
    const SHIPPING_METHOD_INPOST_CROSSBORDER_FORM = 'inpost_parcellocker/checkout_shipping_method_crossborder_form';
    const GEO_WIDGET_PL = 'https://geowidget-pl.easypack24.net/dropdown.php';
    const GEO_WIDGET_FR = 'https://geowidget-fr.easypack24.net/dropdown.php';
    const GEO_WIDGET_IT = 'https://geowidget-it.easypack24.net/dropdown.php';
    const GEO_WIDGET_CROSSBORDER = 'https://widget-xborder-inpost.sheepla.com/js/SheeplaLib.js';
    const GEO_WIDGET_CROSSBORDER_STYLE = 'https://widget-xborder-inpost.sheepla.com/css/SheeplaCrossBorder.css';
    const GEO_WIDGET_MAIN_CONFIG_SELECT_NAME = 'groups[sender_address][fields][default_parcellocker][value]';
    const GEO_WIDGET_MAIN_CONFIG_SELECT_ID = 'inpost_parcellocker_sender_address_default_parcellocker';

    protected $_parcellockerCode = 'inpostparcellockers';
    protected $_crossborderCode = 'inpostcrossborder';
    protected $geoWidgetParams = array(
        'dropdown_class' => 'required-entry',
        'dropdown_name' => 'inpost_parcellocker_id',
        'dropdown_id' => 'inpost_parcellocker_id'
    );

    /**
     * @return Inpost_ParcelLocker_Model_Config
     */
    public function getConfig() {
        return Mage::getSingleton('inpost_parcellocker/config');
    }

    /**
     * Insert Inpost needed blocks to magento
     * @param Varien_Event_Observer $observer
     */
    public function insertInpostBlocks(Varien_Event_Observer $observer) {
        $event = $observer->getEvent();
        $block = $event->getBlock();
        $blockType = $block->getType();

        if ($blockType == self::SHIPPING_METHOD_BLOCK_TYPE || $blockType == self::SHIPPING_METHOD_BLOCK_TYPE_LOTUS) {
            $this->insertShippingMethodsBlocks($event);
        } elseif ($blockType == self::FRONTEND_HEAD_BLOCK_TYPE) {
            $this->insertFrontendGeowidget($event);
        } elseif ($blockType == self::BACKEND_HEAD_BLOCK_TYPE) {
            $this->insertBackendGeowidget($event);
        }
    }

    /**
     * Insert Inpost needed code to magento
     * @param Varien_Event_Observer $observer
     */
    public function adminhtmlWidgetContainerHtmlBefore(Varien_Event_Observer $observer) {
        if ($this->getConfig()->moduleAvailable()) {
            $event = $observer->getEvent();
            $block = $event->getBlock();
            if ($block instanceof Mage_Adminhtml_Block_Sales_Order_Shipment_View) {
                $this->insertShipmentLabelButton($block);
                $this->updateShipmentBackButton($block);
            }
        }
    }

    /**
     * Change back button 
     * @param object $block
     */
    protected function updateShipmentBackButton($block) {
        if ($block->getShipment()->getInpostParcelId()) {
            $params = Mage::app()->getRequest()->getParams();
            if (!empty($params['come_from'])) {
                switch ($params['come_from']) {
                    case 'inpost_shipment_list':
                        $block->removeButton('back');
                        $block->addButton('back', array(
                            'label' => __('Back'),
                            'onclick' => 'setLocation(\'' . $block->getUrl('*/inpost_shipment_list/index') . '\')',
                            'class' => 'back'
                                ), 0, -1, 'header');
                        break;
                }
            }
        }
    }

    /**
     * Insert "Generate/Download Shipment Label" button to shipment view page 
     * @param object $block
     */
    protected function insertShipmentLabelButton($block) {
        $helper = Mage::helper('inpost_parcellocker');
        $shipment = $block->getShipment();
        if ($shipment->getInpostParcelId()) {
            if ($shipment->getInpostShippingLabelGenerated()) {

                /* Make payment for parcel in InPost service */
                $url = $block->getUrl('*/inpost_shipment/label', array('shipment_id' => $block->getShipment()->getId()));
                $block->addButton('inpost_shipping_label', array(
                    'label' => $helper->__('Download Shipping Label'),
                    'class' => 'save',
                    'onclick' => 'setLocation(\'' . $url . '\')'
                        )
                );
            } else {

                /* Generate shipment label */
                $url = $block->getUrl('*/inpost_shipment/label', array('shipment_id' => $block->getShipment()->getId()));
                $block->addButton('inpost_shipping_label', array(
                    'label' => $helper->__('Generate Shipping Label'),
                    'class' => 'save',
                    'onclick' => 'setLocation(\'' . $url . '\')'
                        )
                );
            }
        }
    }

    /**
     * Insert frontend geowidget on checkout pages
     * @param object $event
     */
    protected function insertFrontendGeowidget($event) {
        if ($this->getConfig()->moduleAvailable()) {
            $request = Mage::app()->getRequest();
            $moduleName = $request->getModuleName();
            if ($moduleName == 'checkout' || $moduleName == 'onestepcheckout') {
                $this->getInsertGeowidgetJs($event, true);
            }
        }
    }

    /**
     * Insert backend geowidget
     * @param object $event
     */
    protected function insertBackendGeowidget($event) {
        $request = Mage::app()->getRequest();
        $controller = $request->getControllerName();
        $params = $request->getParams();
        $section = isset($params['section']) ? $params['section'] : null;
        if ($controller == 'inpost_shipment') {

            /* Insert geowidget in shipment information edit page */
            $this->getInsertGeowidgetJs($event, false);
        } elseif ($section == 'inpost_parcellocker') {

            /* Insert geowidget in module configuration page */
            $params = array(
                'dropdown_class' => 'required-entry',
                'dropdown_name' => self::GEO_WIDGET_MAIN_CONFIG_SELECT_NAME,
                'dropdown_id' => self::GEO_WIDGET_MAIN_CONFIG_SELECT_ID
            );
            $this->getInsertGeowidgetJs($event, false, $params);
        }
    }

    /**
     * Get geowidget javascript depends on market type
     * @return string
     */
    protected function getInsertGeowidgetJs($event, $front, $params = null) {
        $html = $event->getTransport()->getHtml();
        $geoWidgetParams = isset($params) ? $params : $this->geoWidgetParams;
        $marketType = $this->getConfig()->getMarketType();
        $widget = null;
        $paramsString = '?';

        /* Create params string for url */
        foreach ($geoWidgetParams as $key => $value) {
            $paramsString .= $key . '=' . $value . '&';
        }

        /* Select geowidget depends on market type */
        if ($marketType == 'pl') {
            $widget = '<script type="text/javascript" src="' . self::GEO_WIDGET_PL . $paramsString . '"></script>';
        } elseif ($marketType == 'it') {
            $widget = '<script type="text/javascript" src="' . self::GEO_WIDGET_IT . $paramsString . '"></script>';
        } elseif ($marketType == 'fr') {
            $widget = '<script type="text/javascript" src="' . self::GEO_WIDGET_FR . $paramsString . '"></script>';
        }

        if ($front) {
            /* insert crossborder geowidget and css */
            $widget .= '<script type="text/javascript" src="' . self::GEO_WIDGET_CROSSBORDER . '"></script>';
            $widget .= '<link rel="stylesheet" type="text/css" href="' . self::GEO_WIDGET_CROSSBORDER_STYLE . '" media="all">';
        }

        $event->getTransport()->setHtml($html . $widget);
    }

    /**
     * Insert blocks with module description and logotype in shipping methods checkout section
     * @param object $event
     */
    protected function insertShippingMethodsBlocks($event) {
        if ($this->getConfig()->moduleAvailable()) {
            $blocks = array();
            if ($this->getConfig()->shippingMethodAvailable($this->_parcellockerCode)) {

                $blocks['parcellocker_description'] = array(
                    'block' => self::SHIPPING_METHOD_INPOST_PARCELLOCKER_DESCRIPTION,
                    'block_name' => 'inpost.parcellocker.description'
                );
                $blocks['parcellocker_form'] = array(
                    'block' => self::SHIPPING_METHOD_INPOST_PARCELLOCKER_FORM,
                    'block_name' => 'inpost.parcellocker.form'
                );
            }
            if ($this->getConfig()->isCrossborderAvailable() &&
                    $this->getConfig()->shippingMethodAvailable($this->_crossborderCode)) {

                $blocks['crossborder_description'] = array(
                    'block' => self::SHIPPING_METHOD_INPOST_CROSSBORDER_DESCRIPTION,
                    'block_name' => 'inpost.crossborder.description'
                );
                $blocks['crossborder_form'] = array(
                    'block' => self::SHIPPING_METHOD_INPOST_CROSSBORDER_FORM,
                    'block_name' => 'inpost.crossborder.form'
                );
            }
            if (!empty($blocks)) {
                foreach ($blocks as $block) {
                    $html = $event->getTransport()->getHtml();
                    $frame = $event->getBlock()->getLayout()
                            ->createBlock($block['block'], $block['block_name'])
                            ->toHtml();
                    $event->getTransport()->setHtml($html . $frame);
                }
            }
        }


    }

    /**
     * Add layout handle depends on market type
     * @param Varien_Event_Observer $observer
     */
    public function addMarketHandle(Varien_Event_Observer $observer) {
        if ($this->getConfig()->moduleAvailable()) {
            $market = $this->getConfig()->getMarketType();
            /* @var $update Mage_Core_Model_Layout_Update */
            $update = $observer->getEvent()->getLayout()->getUpdate();
            $update->addHandle('inpost_market_' . $market);
        }
    }

    /**
     * Throw InPost Exception
     * @param string $message
     * @throws Inpost_ParcelLocker_Model_Exception
     */
    protected function throwException($message) {
        throw new Inpost_ParcelLocker_Model_Exception($message);
    }

}

W zasadzie to tyle – po tych zmianach wszystko działa jak trzeba. Przypuszczam, że miejsca w kodzie, które zmodyfikowałem są kluczowe do integracji modułu z dowolnym modułem koszyka Magento.

Dodaj komentarz

Podobne artykuły