2

I am trying to override Magento 2 sales order totals block. I am setting preference for the same in my custom module as the function to be overridden is protected function, please find code below:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for='Magento\Sales\Block\Order\Totals' type='Company\Module\Block\Order\Totals'/>
</config> 

The custom block file being used to override the same is as below:

<?php

namespace Company\Module\Block\Order;

use Magento\Sales\Model\Order;

class Totals extends \Magento\Sales\Block\Order\Totals
{
    /**
     * Associated array of totals
     * array(
     *  $totalCode => $totalObject
     * )
     *
     * @var array
     */
    protected $_totals;

    /**
     * @var Order|null
     */
    protected $_order = null;

    /**
     * Core registry
     *
     * @var \Magento\Framework\Registry
     */
    protected $_coreRegistry = null;

    /**
     * @param \Magento\Framework\View\Element\Template\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Framework\Registry $registry,
        array $data = []
    ) {
        parent::__construct($context, $registry, $data);
    }

    /**
     * Initialize self totals and children blocks totals before html building
     *
     * @return $this
     */
    protected function _beforeToHtml()
    {
        $this->_initTotals();
        foreach ($this->getLayout()->getChildBlocks($this->getNameInLayout()) as $child) {
            if (method_exists($child, 'initTotals') && is_callable([$child, 'initTotals'])) {
                $child->initTotals();
            }
        }
        return parent::_beforeToHtml();
    }

    /**
     * Initialize order totals array
     *
     * @return $this
     */
    protected function _initTotals()
    {
        $source = $this->getSource();

        $this->_totals = [];
        $this->_totals['subtotal'] = new \Magento\Framework\DataObject(
            ['code' => 'subtotal', 'value' => $source->getSubtotal(), 'label' => __('Subtotal')]
        );

        /**
         * Add shipping
         */
        if (!$source->getIsVirtual() && ((double)$source->getShippingAmount() || $source->getShippingDescription())) {
            $this->_totals['shipping'] = new \Magento\Framework\DataObject(
                [
                    'code' => 'shipping',
                    'field' => 'shipping_amount',
                    'value' => $this->getSource()->getShippingAmount(),
                    'label' => __('Shipping & Handling'),
                ]
            );
        }

        /**
         * Add discount
         */
        if ((double)$this->getSource()->getDiscountAmount() != 0) {
            if ($this->getSource()->getDiscountDescription()) {
                $discountLabel = __('Discount (%1)', $source->getDiscountDescription());
            } else {
                $discountLabel = __('Discount');
            }
            $this->_totals['discount'] = new \Magento\Framework\DataObject(
                [
                    'code' => 'discount',
                    'field' => 'discount_amount',
                    'value' => $source->getDiscountAmount(),
                    'label' => $discountLabel,
                ]
            );
        }

        $this->_totals['grand_total'] = new \Magento\Framework\DataObject(
            [
                'code' => 'grand_total',
                'field' => 'grand_total',
                'strong' => true,
                'value' => $source->getGrandTotal(),
                'label' => __('Grand Total'),
            ]
        );

        /**
         * Base grandtotal
         */
        if ($this->getOrder()->isCurrencyDifferent()) {
            $this->_totals['base_grandtotal'] = new \Magento\Framework\DataObject(
                [
                    'code' => 'base_grandtotal',
                    'value' => $this->getOrder()->formatBasePrice($source->getBaseGrandTotal()),
                    'label' => __('Grand Total to be Charged'),
                    'is_formated' => true,
                ]
            );
        }
        return $this;
    }
}

I can see the function is overwritten and called via my custom block but it is not being rendered at orders total section. Order total section is gone blank, not sure why it is happening so. Please suggest me if anyone have idea on it.

1 Answer 1

2

You have to create layout sales_order_view and create block in container reference of order_totals.

 <referenceContainer name="order_totals">   

<block class="[company]\[module]\Block\Sales\Totals\custom" name="custom" as="custom"/>
  </referenceContainer>

Block for order_totals

class custom extends \Magento\Framework\View\Element\Template {

protected $_order;
protected $_source;

public function __construct(\Magento\Framework\View\Element\Template\Context $context,
    array $data = []
    ) {
    parent :: __construct($context, $data);
} 

public function getSource() {
    return $this -> _source;
} 

public function getStore() {
    return $this -> _order -> getStore();
} 

public function getOrder() {
    return $this -> _order;
} 


public function initTotals() {
    $parent = $this -> getParentBlock();
    $this -> _order = $parent -> getOrder();
    $this -> _source = $parent -> getSource();

    $custom = new \Magento\Framework\DataObject([
        'code' => 'custom',
        'strong' => false,
        'value' => [value],
        'label' =>[label],
        ]
        );

    $parent -> addTotal($custum, 'custom');

    return $this;
} 
} 

Here i add custom field in order_totals reference block.

3
  • Where do I need to call this custom.php file
    – Vindhuja
    Commented Dec 11, 2017 at 8:55
  • In sales_order_view.xml layout file . Commented Dec 13, 2017 at 8:36
  • thanks, you saved my time. Commented Apr 16, 2020 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.