Showing posts with label adminpanel. Show all posts
Showing posts with label adminpanel. Show all posts

2016/11/07

How to display M2E order data or a product attribute in the Magento order grid

Lets assume you wish to extend your Magento order grid in the admin panel with a new column that displays an attribute of the ordered products to get a better overview for your shipping processes.

The most small or midsize online shops use the order grid to manage their shipments with export bulk methods or directly through the grid table.

Therefor it is comfortable to have all information needed in this grid. In this little how-to we will extend our grid to display order information of the m2e module and another example with a product attribute. You can customize the code to get any other attribute.

Create a local module to extend the order grid

We assume that you know how to create a new local module.
Create a proper config/etc.xml.

First create the Grid.php block which will override the core block in the default sales module. Copy your orignal Mage_Adminhtml_Block_Sales_Order_Grid an paste it into your new file. Then it might look like the following class.
Yourname_Yourmodule_Block_Adminhtml_Sales_Order_Grid:

class Yourname_Yourmodule_Block_Adminhtml_Sales_Order_Grid
    extends Mage_Adminhtml_Block_Widget_Grid
{

    public function __construct()
    {
        parent::__construct();
        $this->setId('sales_order_grid');
        $this->setUseAjax(true);
        $this->setDefaultSort('created_at');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
    }

    /**
     * Retrieve collection class
     *
     * @return string
     */
    protected function _getCollectionClass()
    {
        return 'sales/order_grid_collection';
    }

    protected function _prepareCollection()
    {
        $collection = Mage::getResourceModel($this->_getCollectionClass());

        $this->setCollection($collection);
        return parent::_prepareCollection();
    }

    protected function _prepareColumns()
    {
        $this->addColumn('real_order_id', array(
            'header'=> Mage::helper('sales')->__('Order #'),
            'width' => '80px',
            'type'  => 'text',
            'index' => 'increment_id',
        ));

        if (!Mage::app()->isSingleStoreMode()) {
            $this->addColumn('store_id', array(
                'header'    => Mage::helper('sales')->__('Purchased From (Store)'),
                'index'     => 'store_id',
                'type'      => 'store',
                'store_view'=> true,
                'display_deleted' => true,
            ));
        }

        $this->addColumn('created_at', array(
            'header' => Mage::helper('sales')->__('Purchased On'),
            'index' => 'created_at',
            'type' => 'datetime',
            'width' => '100px',
        ));

        $this->addColumn('billing_name', array(
            'header' => Mage::helper('sales')->__('Bill to Name'),
            'index' => 'billing_name',
        ));

        $this->addColumn('shipping_name', array(
            'header' => Mage::helper('sales')->__('Ship to Name'),
            'index' => 'shipping_name',
        ));

        $this->addColumn('base_grand_total', array(
            'header' => Mage::helper('sales')->__('G.T. (Base)'),
            'index' => 'base_grand_total',
            'type'  => 'currency',
            'currency' => 'base_currency_code',
        ));

        $this->addColumn('grand_total', array(
            'header' => Mage::helper('sales')->__('G.T. (Purchased)'),
            'index' => 'grand_total',
            'type'  => 'currency',
            'currency' => 'order_currency_code',
        ));

        $this->addColumn('order_type', array(
            'header' => Mage::helper('sales')->__('Order Type'),
            'width' => '100px',
            'align' => 'left',
            'index' => 'order_type',
            'renderer' => 'yourmodule/adminhtml_sales_grid_renderer_m2eAttribute',
            'filter_condition_callback' => array($this, '_filterM2eConditionCallback')
        ));

        $this->addColumn('status', array(
            'header' => Mage::helper('sales')->__('Status'),
            'index' => 'status',
            'type'  => 'options',
            'width' => '70px',
            'options' => Mage::getSingleton('sales/order_config')->getStatuses(),
        ));

        if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/view')) {
            $this->addColumn('action',
                array(
                    'header'    => Mage::helper('sales')->__('Action'),
                    'width'     => '50px',
                    'type'      => 'action',
                    'getter'     => 'getId',
                    'actions'   => array(
                        array(
                            'caption' => Mage::helper('sales')->__('View'),
                            'url'     => array('base'=>'*/sales_order/view'),
                            'field'   => 'order_id'
                        )
                    ),
                    'filter'    => false,
                    'sortable'  => false,
                    'index'     => 'stores',
                    'is_system' => true,
            ));
        }

        $this->addRssList('rss/order/new', Mage::helper('sales')->__('New Order RSS'));

        $this->addExportType('*/*/exportCsv', Mage::helper('sales')->__('CSV'));
        $this->addExportType('*/*/exportExcel', Mage::helper('sales')->__('Excel XML'));

        return parent::_prepareColumns();
    }

    protected function _prepareMassaction()
    {
        $this->setMassactionIdField('entity_id');
        $this->getMassactionBlock()->setFormFieldName('order_ids');
        $this->getMassactionBlock()->setUseSelectAll(false);

        if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/cancel')) {
            $this->getMassactionBlock()->addItem('cancel_order', array(
                 'label'=> Mage::helper('sales')->__('Cancel'),
                 'url'  => $this->getUrl('*/sales_order/massCancel'),
            ));
        }

        if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/hold')) {
            $this->getMassactionBlock()->addItem('hold_order', array(
                 'label'=> Mage::helper('sales')->__('Hold'),
                 'url'  => $this->getUrl('*/sales_order/massHold'),
            ));
        }

        if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/unhold')) {
            $this->getMassactionBlock()->addItem('unhold_order', array(
                 'label'=> Mage::helper('sales')->__('Unhold'),
                 'url'  => $this->getUrl('*/sales_order/massUnhold'),
            ));
        }

        $this->getMassactionBlock()->addItem('pdfinvoices_order', array(
             'label'=> Mage::helper('sales')->__('Print Invoices'),
             'url'  => $this->getUrl('*/sales_order/pdfinvoices'),
        ));

        $this->getMassactionBlock()->addItem('pdfshipments_order', array(
             'label'=> Mage::helper('sales')->__('Print Packingslips'),
             'url'  => $this->getUrl('*/sales_order/pdfshipments'),
        ));

        $this->getMassactionBlock()->addItem('pdfcreditmemos_order', array(
             'label'=> Mage::helper('sales')->__('Print Credit Memos'),
             'url'  => $this->getUrl('*/sales_order/pdfcreditmemos'),
        ));

        $this->getMassactionBlock()->addItem('pdfdocs_order', array(
             'label'=> Mage::helper('sales')->__('Print All'),
             'url'  => $this->getUrl('*/sales_order/pdfdocs'),
        ));

        $this->getMassactionBlock()->addItem('print_shipping_label', array(
             'label'=> Mage::helper('sales')->__('Print Shipping Labels'),
             'url'  => $this->getUrl('*/sales_order_shipment/massPrintShippingLabel'),
        ));

        return $this;
    }

    public function getRowUrl($row)
    {
        if (Mage::getSingleton('admin/session')->isAllowed('sales/order/actions/view')) {
            return $this->getUrl('*/sales_order/view', array('order_id' => $row->getId()));
        }
        return false;
    }

    public function getGridUrl()
    {
        return $this->getUrl('*/*/grid', array('_current'=>true));
    }

    /**
     * filter callback to find the order_type
     * of orders through m2e (amazon, ebay, ...)
     *
     * @param object $collection
     * @param object $column
     * @return Yourname_Yourmodule_Block_Adminhtml_Sales_Order_Grid
     */
    public function _filterM2eConditionCallback($collection, $column) {
        if (!$value = $column->getFilter()->getValue()) {
            return $this;
        }
        if (!empty($value) && strtolower($value) != 'magento') {
            $this->getCollection()->getSelect()
                ->join(
                    'm2epro_order',
                    'main_table.entity_id=m2epro_order.magento_order_id',
                    array('component_mode')
                    )
                ->where(
                 'm2epro_order.component_mode = "' . strtolower($value) . '"');
        } elseif(strtolower($value) == 'magento') {
            $this->getCollection()->getSelect()
                ->join(
                    'm2epro_order',
                    'main_table.entity_id=m2epro_order.magento_order_id',
                    array('component_mode')
                    )
                ->where(
                 'm2epro_order.component_mode = NULL');
        }

        return $this;
    }
}

What has changed to the original class, is the following snippet to add a new column and the relating callback method named _filterM2eConditionCallback.


$this->addColumn('order_type', array(
    'header' => Mage::helper('sales')->__('Order Type'),
    'width' => '100px',
    'align' => 'left',
    'index' => 'order_type',
    'renderer' => 'yourmodule/adminhtml_sales_grid_renderer_m2eAttribute',
    'filter_condition_callback' => array($this, '_filterM2eConditionCallback')
));

As you can see, the column has a filter_condition_callback which manage the select to filter through the right tables. The renderer block is the other thing that is special about our column. The renderer will take care of the value that is displayed in the column. Lets take a look at the renderer:
Yourname_Yourmodule_Block_Adminhtml_Sales_Grid_Renderer_M2eAttribute


class Yourname_Yourmodule_Block_Adminhtml_Sales_Grid_Renderer_M2eAttribute
    extends Mage_Adminhtml_Block_Widget_Grid_Column_Renderer_Abstract
{
    public function render(Varien_Object $row)
    {
        // do whatever you need, to display your data
        // get the id of the row order data
        $orderId = $row->getEntityId();
        // get the related m2e order data
        $orders = Mage::getModel('M2ePro/Order')
            ->getCollection()
            ->addFieldToSelect('component_mode')
            ->addFieldToFilter('magento_order_id', $orderId);

        if($orders) {
            $data = $orders->getFirstItem()->getData();
            if(isset($data['component_mode'])) {
                return ucfirst($data['component_mode']);
            }
        }
        // return the string "magento" if there is no m2e relation
        return 'Magento';
    }
}

Now we look at the filter callback:


/**
 * filter callback to find the order_type
 * of orders through m2e (amazon, ebay, ...)
 *
 * @param object $collection
 * @param object $column
 * @return Yourname_Yourmodule_Block_Adminhtml_Sales_Order_Grid
 */
public function _filterM2eConditionCallback($collection, $column) {
    if (!$value = $column->getFilter()->getValue()) {
        return $this;
    }
    if (!empty($value) && strtolower($value) != 'magento') {
        $this->getCollection()->getSelect()
            // join to the m2mepro order table and select component_mode
            ->join(
                'm2epro_order',
                'main_table.entity_id=m2epro_order.magento_order_id',
                array('component_mode')
                )
            ->where(
             'm2epro_order.component_mode = "' . strtolower($value) . '"');
    } elseif(strtolower($value) == 'magento') {
        $this->getCollection()->getSelect()
            ->join(
                'm2epro_order',
                'main_table.entity_id=m2epro_order.magento_order_id',
                array('component_mode')
                )
            ->where(
             'm2epro_order.component_mode = NULL');
    }

    return $this;
}


Another example to select a product attribute in the order grid

This is an example of a filter callback to get data of a specific product attribute:


public function _filterShippingCostConditionCallback($collection, $column) {
    if (!$value = $column->getFilter()->getValue()) {
        return $this;
    }
    if (!empty($value)) {
        $this->getCollection()->getSelect()
            // join to to the flat order item table
            ->join(
                'sales_flat_order_item',
                'main_table.entity_id=sales_flat_order_item.order_id',
                array('product_id')
                )
            // join to the value table for the products
            ->join(
                'catalog_product_entity_decimal',
                'sales_flat_order_item.product_id=catalog_product_entity_decimal.entity_id',
                array('value')
            )
            // where condition to select the value
            ->where(
                // attribute_id relates to your attribute
             'catalog_product_entity_decimal.value = "' . ($value) . '" AND catalog_product_entity_decimal.attribute_id=247');
    }
    return $this;
}


The first join will get the table of the order items, to get the relation between the order and the ordered items. From there we join the second table from the product id of the previously selected items. Here you have to check which of the eav table has your attribute value. If you have an attribute with a text field. catalog_product_entity_varchar will be the right one.

In the condition you have to adapt the attribute_id to the one you are trying to select.

Now go to your adminpanel and check the result.

2016/10/29

How to pay with Paypal in Magento from the Admin Panel?

If you or your sales team creates orders for your customers over the Magento adminpanel sometimes, you might came to this issue: You cannot select Paypal in the Backend order.

This seems logical if you think about the Paypal payment process: after the checkout you are redirected to the Paypal website for the purchase. This is not possible in a situation, where you are creating an order for a customer, because you do not have his password (e.g. if you talk with the customer on the phone or in person in your local store). This is a general issue for all payment options like Paypal like Sofort.com, Klarna, Billsafe and so on.

But with a little workaround, you can easily let your customers pay with Paypal while you are ordering for him in the Magento Backend.

The solution

We are adding a Backend Payment method which is called "Paypal" with no further program logic. This ensures, the order and invoice information shows the correct payment method.

BackendPayment provides payment methods like cash, debit and Paypal
After we created the order, we go to our the official Paypal website and use the "Request money" function. This allows you to enter the Paypal Email address of your customer and the amount of the order to request the money over Paypal.

For the developers 

It is easy to provide a new payment method which is only available in the admin panel and not on the customers checkout. Just create a new module with the default folders and configuration for at least models, blocks and helpers.

The first thing you need is a model which looks like the following (you have to change class names to your correct namespace):

/**
 * Grafzahl_BackendPayments
 *
 * @category    Grafzahl
 * @package     Grafzahl_BackendPayments
 * @copyright   Copyright (c) 2016 Grafzahl (https://grafzahl.io)
 * @license     https://grafzahl.io/license
 */

class Grafzahl_BackendPayments_Model_PaypalPayment
    extends Mage_Payment_Model_Method_Abstract
{
    protected $_code = 'backendpayments_paypal';
    protected $_infoBlockType = 'backendpayments/info';
    protected $_canUseInternal = true;
    protected $_canUseCheckout = false;
    protected $_canUseForMultishipping  = false;

    public function __construct()
    {
        parent::__construct();
    }
}

The second thing is to create the related block from the model in the attribute $_infoBlockType. The block just needs to extend the block Mage_Payment_Block_Info. Now check the extending block and update the methods to your needs.

Complete ready to use solution

Such a payment method, mentioned above is already available. You can download BackendPayments from our grafzahl.io store and install it in your Magento store from version 1.7.x - 1.9.x with no pain.

This will provide you three new payment methods in your admin panel order form: Paypal, Debit and Cash. You can even use any other payment provider instead of Paypal. The title can be edited in the system configuration.

With this module you can also create order with the method Cash payment and Debit Payment. If you have a little local store which you manage with a Magento Shop-System, you will be able to create orders with cash payment from your admin panel.

You can also configure if these methods should automatically create the invoice for you. For further information, check our documentation source.


2010/01/18

Magento Admin Panel: Überblick über die Funktionen und Bedienelemente

In diesem Post möchte ich Ihnen einen Überblick über die wichtigesten Funktionen von Magento geben, die man als Shopbetreiber bei der alltäglichen Arbeit benötigt.

Dazu rufen wir als erstes unser Magento Admin Panel über die Adresszeile im Browser auf. Für die Standardinstallation ist das www.ihrshop.de/admin.
Es wird allerdings empfohlen die Adresse für die Life-Version zu ändern. Dies ist sicherer, da das System so weniger angreifbar ist.