45

The following link will describe

http://excellencemagentoblog.com/blog/2012/01/27/magento-add-fee-discount-order-total/

to add fee to order totals in Magento 1.

Now this functionality is moved to Quote module in Magento 2 .

I think still same concept like collect and fetch methods. Has anyone tried this in Magento 2?

7ochem
  • 7,532
  • 14
  • 51
  • 80
Sivakumar K
  • 2,013
  • 9
  • 27
  • 43

6 Answers6

130

follow below steps it will help you, in my module, I just added fee column
this will add one row in cart total called fee and also side bar in the checkout page
and also it added fee amount to total amount (fee static value I kept as 100) once the order is placed total will be with fee and if you are logged in fronted in order view you can see fee's new row in the total block but admin side not yet implemented if someone implements, you can post that answer

create sales.xml in your module etc folder

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Sales:etc/sales.xsd"> <section name="quote"> <group name="totals">

        &lt;item name=&quot;fee&quot; instance=&quot;Sugarcode\Test\Model\Total\Fee&quot; sort_order=&quot;150&quot;/&gt;

    &lt;/group&gt;  
&lt;/section&gt;

</config>

app\code\Sugarcode\Test\view\frontend\web\js\view\checkout\cart\totals\fee.js

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
define(
    [
        'Sugarcode_Test/js/view/checkout/summary/fee'
    ],
    function (Component) {
        'use strict';
    return Component.extend({

        /**
         * @override
         */
        isDisplayed: function () {
            return true;
        }
    });
}

);

app\code\Sugarcode\Test\view\frontend\web\js\view\checkout\summary\fee.js

/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
/*jshint browser:true jquery:true*/
/*global alert*/
define(
    [
        'Magento_Checkout/js/view/summary/abstract-total',
        'Magento_Checkout/js/model/quote',
        'Magento_Catalog/js/price-utils',
        'Magento_Checkout/js/model/totals'
    ],
    function (Component, quote, priceUtils, totals) {
        "use strict";
        return Component.extend({
            defaults: {
                isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,
                template: 'Sugarcode_Test/checkout/summary/fee'
            },
            totals: quote.getTotals(),
            isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,
            isDisplayed: function() {
                return this.isFullMode();
            },
            getValue: function() {
                var price = 0;
                if (this.totals()) {
                    price = totals.getSegment('fee').value;
                }
                return this.getFormattedPrice(price);
            },
            getBaseValue: function() {
                var price = 0;
                if (this.totals()) {
                    price = this.totals().base_fee;
                }
                return priceUtils.formatPrice(price, quote.getBasePriceFormat());
            }
        });
    }
);

app\code\Sugarcode\Test\view\frontend\web\template\checkout\summary\fee.html

<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<!-- ko -->

<tr class="totals fee excl"> <th class="mark" scope="row"> <span class="label" data-bind="text: title"></span> <span class="value" data-bind="text: getValue()"></span> </th> <td class="amount">

        &lt;span class=&quot;price&quot;
              data-bind=&quot;text: getValue(), attr: {'data-th': title}&quot;&gt;&lt;/span&gt;


    &lt;/td&gt;
&lt;/tr&gt;   

<!-- /ko -->

app\code\Sugarcode\Test\view\frontend\web\template\checkout\cart\totals\fee.html

<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<!-- ko -->
<tr class="totals fee excl">
    <th class="mark" colspan="1" scope="row" data-bind="text: title"></th>
    <td class="amount">
        <span class="price" data-bind="text: getValue()"></span>
    </td>
</tr>
<!-- /ko -->

app\code\Sugarcode\Test\Model\Total\Fee.php

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Sugarcode\Test\Model\Total;

class Fee extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal { /** * Collect grand total address amount * * @param \Magento\Quote\Model\Quote $quote * @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment * @param \Magento\Quote\Model\Quote\Address\Total $total * @return $this */ protected $quoteValidator = null;

public function __construct(\Magento\Quote\Model\QuoteValidator $quoteValidator)
{
    $this-&gt;quoteValidator = $quoteValidator;
}

public function collect( \Magento\Quote\Model\Quote $quote, \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment, \Magento\Quote\Model\Quote\Address\Total $total ) { parent::collect($quote, $shippingAssignment, $total);

    $exist_amount = 0; //$quote-&gt;getFee(); 
    $fee = 100; //Excellence_Fee_Model_Fee::getFee();
    $balance = $fee - $exist_amount;

    $total-&gt;setTotalAmount('fee', $balance);
    $total-&gt;setBaseTotalAmount('fee', $balance);

    $total-&gt;setFee($balance);
    $total-&gt;setBaseFee($balance);

    $total-&gt;setGrandTotal($total-&gt;getGrandTotal() + $balance);
    $total-&gt;setBaseGrandTotal($total-&gt;getBaseGrandTotal() + $balance);


    return $this;
} 

protected function clearValues(Address\Total $total)
{
    $total-&gt;setTotalAmount('subtotal', 0);
    $total-&gt;setBaseTotalAmount('subtotal', 0);
    $total-&gt;setTotalAmount('tax', 0);
    $total-&gt;setBaseTotalAmount('tax', 0);
    $total-&gt;setTotalAmount('discount_tax_compensation', 0);
    $total-&gt;setBaseTotalAmount('discount_tax_compensation', 0);
    $total-&gt;setTotalAmount('shipping_discount_tax_compensation', 0);
    $total-&gt;setBaseTotalAmount('shipping_discount_tax_compensation', 0);
    $total-&gt;setSubtotalInclTax(0);
    $total-&gt;setBaseSubtotalInclTax(0);
}
/**
 * @param \Magento\Quote\Model\Quote $quote
 * @param Address\Total $total
 * @return array|null
 */
/**
 * Assign subtotal amount and label to address object
 *
 * @param \Magento\Quote\Model\Quote $quote
 * @param Address\Total $total
 * @return array
 * @SuppressWarnings(PHPMD.UnusedFormalParameter)
 */
public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total)
{
    return [
        'code' =&gt; 'fee',
        'title' =&gt; 'Fee',
        'value' =&gt; 100
    ];
}

/**
 * Get Subtotal label
 *
 * @return \Magento\Framework\Phrase
 */
public function getLabel()
{
    return __('Fee');
}

}

app\code\Sugarcode\Test\etc\module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Sugarcode_Test" setup_version="2.0.6" schema_version="2.0.6">
        <sequence>
            <module name="Magento_Sales"/>
            <module name="Magento_Quote"/>
            <module name="Magento_Checkout"/>
        </sequence>
    </module>
</config>

app\code\Sugarcode\Test\view\frontend\layout\checkout_cart_index.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.cart.totals">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="block-totals" xsi:type="array">
                            <item name="children" xsi:type="array">
                            &lt;item name=&quot;fee&quot; xsi:type=&quot;array&quot;&gt;
                                &lt;item name=&quot;component&quot;  xsi:type=&quot;string&quot;&gt;Sugarcode_Test/js/view/checkout/cart/totals/fee&lt;/item&gt;
                                &lt;item name=&quot;sortOrder&quot; xsi:type=&quot;string&quot;&gt;20&lt;/item&gt;
                                &lt;item name=&quot;config&quot; xsi:type=&quot;array&quot;&gt;
                                     &lt;item name=&quot;template&quot; xsi:type=&quot;string&quot;&gt;Sugarcode_Test/checkout/cart/totals/fee&lt;/item&gt;
                                    &lt;item name=&quot;title&quot; xsi:type=&quot;string&quot; translate=&quot;true&quot;&gt;Fee&lt;/item&gt;
                                &lt;/item&gt;
                            &lt;/item&gt;

                        &lt;/item&gt;
                    &lt;/item&gt;
                &lt;/item&gt;
            &lt;/argument&gt;
        &lt;/arguments&gt;
    &lt;/referenceBlock&gt;
&lt;/body&gt;

</page>

app\code\Sugarcode\Test\view\frontend\layout\checkout_index_index.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                            &lt;item name=&quot;sidebar&quot; xsi:type=&quot;array&quot;&gt;
                                &lt;item name=&quot;children&quot; xsi:type=&quot;array&quot;&gt;
                                    &lt;item name=&quot;summary&quot; xsi:type=&quot;array&quot;&gt;
                                        &lt;item name=&quot;children&quot; xsi:type=&quot;array&quot;&gt;
                                            &lt;item name=&quot;totals&quot; xsi:type=&quot;array&quot;&gt;
                                                &lt;item name=&quot;children&quot; xsi:type=&quot;array&quot;&gt;
                                                   &lt;item name=&quot;fee&quot; xsi:type=&quot;array&quot;&gt;
                                                        &lt;item name=&quot;component&quot;  xsi:type=&quot;string&quot;&gt;Sugarcode_Test/js/view/checkout/cart/totals/fee&lt;/item&gt;
                                                        &lt;item name=&quot;sortOrder&quot; xsi:type=&quot;string&quot;&gt;20&lt;/item&gt;
                                                        &lt;item name=&quot;config&quot; xsi:type=&quot;array&quot;&gt;
                                                             &lt;item name=&quot;template&quot; xsi:type=&quot;string&quot;&gt;Sugarcode_Test/checkout/cart/totals/fee&lt;/item&gt;
                                                            &lt;item name=&quot;title&quot; xsi:type=&quot;string&quot; translate=&quot;true&quot;&gt;Fee&lt;/item&gt;
                                                        &lt;/item&gt;
                                                    &lt;/item&gt;
                                                &lt;/item&gt;
                                            &lt;/item&gt;
                                            &lt;item name=&quot;cart_items&quot; xsi:type=&quot;array&quot;&gt;
                                                &lt;item name=&quot;children&quot; xsi:type=&quot;array&quot;&gt;
                                                    &lt;item name=&quot;details&quot; xsi:type=&quot;array&quot;&gt;
                                                        &lt;item name=&quot;children&quot; xsi:type=&quot;array&quot;&gt;
                                                            &lt;item name=&quot;subtotal&quot; xsi:type=&quot;array&quot;&gt;
                                                                &lt;item name=&quot;component&quot; xsi:type=&quot;string&quot;&gt;Magento_Tax/js/view/checkout/summary/item/details/subtotal&lt;/item&gt;
                                                            &lt;/item&gt;
                                                        &lt;/item&gt;
                                                    &lt;/item&gt;
                                                &lt;/item&gt;
                                            &lt;/item&gt;
                                        &lt;/item&gt;
                                    &lt;/item&gt;
                                &lt;/item&gt;
                            &lt;/item&gt;
                        &lt;/item&gt;
                    &lt;/item&gt;
                &lt;/item&gt;
            &lt;/argument&gt;
        &lt;/arguments&gt;
    &lt;/referenceBlock&gt;
&lt;/body&gt;

</page>

app\code\Sugarcode\Test\view\frontend\layout\sales_order_view.xml

<?xml version="1.0"?>
<!--
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
&lt;body&gt;        
    &lt;referenceContainer name=&quot;order_totals&quot;&gt;
        &lt;block class=&quot;Sugarcode\Test\Block\Sales\Order\Fee&quot; name=&quot;fee&quot;/&gt;
    &lt;/referenceContainer&gt;
&lt;/body&gt;

</page>

app\code\Sugarcode\Test\Block\Sales\Order\Fee.php

<?php
/**
 * Copyright © 2015 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */

/**

  • Tax totals modification block. Can be used just as subblock of \Magento\Sales\Block\Order\Totals

*/ namespace Sugarcode\Test\Block\Sales\Order;

class Fee extends \Magento\Framework\View\Element\Template { /** * Tax configuration model * * @var \Magento\Tax\Model\Config */ protected $_config;

/**
 * @var Order
 */
protected $_order;

/**
 * @var \Magento\Framework\DataObject
 */
protected $_source;

/**
 * @param \Magento\Framework\View\Element\Template\Context $context
 * @param \Magento\Tax\Model\Config $taxConfig
 * @param array $data
 */
public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Tax\Model\Config $taxConfig,
    array $data = []
) {
    $this-&gt;_config = $taxConfig;
    parent::__construct($context, $data);
}

/**
 * Check if we nedd display full tax total info
 *
 * @return bool
 */
public function displayFullSummary()
{
    return true;
}

/**
 * Get data (totals) source model
 *
 * @return \Magento\Framework\DataObject
 */
public function getSource()
{
    return $this-&gt;_source;
} 
public function getStore()
{
    return $this-&gt;_order-&gt;getStore();
}

  /**
 * @return Order
 */
public function getOrder()
{
    return $this-&gt;_order;
}

/**
 * @return array
 */
public function getLabelProperties()
{
    return $this-&gt;getParentBlock()-&gt;getLabelProperties();
}

/**
 * @return array
 */
public function getValueProperties()
{
    return $this-&gt;getParentBlock()-&gt;getValueProperties();
}

/**
 * Initialize all order totals relates with tax
 *
 * @return \Magento\Tax\Block\Sales\Order\Tax
 */
 public function initTotals()
{

    $parent = $this-&gt;getParentBlock();
    $this-&gt;_order = $parent-&gt;getOrder();
    $this-&gt;_source = $parent-&gt;getSource();

    $store = $this-&gt;getStore();

    $fee = new \Magento\Framework\DataObject(
            [
                'code' =&gt; 'fee',
                'strong' =&gt; false,
                'value' =&gt; 100,
                //'value' =&gt; $this-&gt;_source-&gt;getFee(),
                'label' =&gt; __('Fee'),
            ]
        );

        $parent-&gt;addTotal($fee, 'fee');

        return $this;
}

}

once the above steps are done run below command this is important else your js & Html files will be missing from pub/static folder. So run below command which will create js and html file in pub/static folder

bin\magento setup:static-content:deploy  

if works accept my answer which helps others

Khoi Ngo
  • 280
  • 3
  • 7
Pradeep Kumar
  • 8,731
  • 12
  • 60
  • 86
  • 27
    you wrote out the module... impressive! +1 for that – Sander Mangel Dec 10 '15 at 11:55
  • 6
    well done praseep – Amit Bera Dec 14 '15 at 17:24
  • i selected this answer as accepted answer 4 days before only.but still I’m getting notification as not selected.there is a issue in bounty functionality – Sivakumar K Dec 15 '15 at 07:00
  • i am not sure, try in flag , that end of my comments there like edit delete flag , try in flag – Pradeep Kumar Dec 15 '15 at 09:02
  • Great article Pradeep, what about admin changes as I can't see any admin related changes in the code above? – stevensagaar Feb 04 '16 at 13:16
  • 4
    hello Pradeep Kumar, great article, but there is one problem with that code, fee add two times into grand total, is there any solution for this? – Sunil Patel Feb 25 '16 at 15:04
  • How to add condition like if order subtotal greater than equal to $120 then add custom fee discount? – sivakumar Jul 08 '16 at 00:23
  • How to use clear values function? I think in your code this function not used in any where .. – sivakumar Jul 08 '16 at 00:42
  • 4
    Has anyone fixed the two time fee applied bug in above code? – Pallavi Sinha Aug 03 '16 at 12:24
  • The "Two Times Fee"-bug is in the last lines of app\code\Sugarcode\Test\Block\Sales\Order\Fee.php... there's a double occurrence of $parent->addTotal($fee, 'fee'); Guys, don't just copy-paste stuff, read and understand what you do... – mybinaryromance Aug 03 '16 at 18:46
  • I have removed that, Still I am getting it twice. any ideas? – Pallavi Sinha Aug 04 '16 at 04:45
  • 4
    I am sorry, I have to apologize. The "Two Times Fee"-Bug is most probably due to the fact that app\code\Sugarcode\Test\Model\Total\Fee.php extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal. As you normally have two Addresses in Checkout (Billing and Shipping) the Quote save gets called twice. There was a similar Behaviour in M1, unfortunately the M1-Fix is not applicable here... – mybinaryromance Aug 11 '16 at 12:33
  • @PradeepKumar do you know how to do this on checkout instead of cart page? – Ekta Puri Sep 13 '16 at 04:57
  • Thanks Pradeep for such a great tutorial. But I want to apply on a button click. I have created a form after discount and I want to add fee on button click. Fee will be collect by textbox on the form. – Manish Sep 16 '16 at 11:20
  • Hello Pardeep, i have followed following url http://webkul.com/blog/display-custom-pricefee-sales-order-view-page/ which is same as your answer. but after i added the last file i.e for the sales order view i get following error on the customer order view page : Notice: Undefined index: class in /var/www/jewel/vendor/magento/framework/View/Layout/Generator/Block.php on line 213 can you help on this ? – Sunil Verma Sep 22 '16 at 07:27
  • delete generation folder – Pradeep Kumar Sep 28 '16 at 13:18
  • I want to insert fee in subtotal on checkbox is checked can anyone please suggest how to do so. – Paras Arora Oct 21 '16 at 11:46
  • I tried to add same label in my account history for invoice page summary, It is coming fine for invoice but not in order info. \app\code\Dischem\Wicode\view\frontend\layout\sales_order_invoice.xml with referenceContainer as 'invoice_totals' . This is working fine but Order summary is not showing label any Idea, what I have missed? – Pallavi Sinha Nov 10 '16 at 13:21
  • 2
    In case people have trouble with the fee/discount being applied twice, see this answer here: http://stackoverflow.com/a/42141291/7540890 – nbjohan Feb 09 '17 at 16:07
  • Works fine everywhere except on order view page on the frontend, it's not showing in order view. @PradeepKumar – Parth Thummar Mar 17 '17 at 08:07
  • How to add this Fee field in adminhtml sales orders totals?? – gajjala sandeep Jun 19 '17 at 12:11
  • How to add a fee from text box https://prnt.sc/hfsni5 /Sivajik34/Customfee/view/frontend/web/template/checkout/cart/totals/fee.html – Nagendra Kodi Nov 27 '17 at 10:19
  • any one implemented it to appear in backend side ? – Jsparo30 Feb 12 '18 at 06:44
  • can anyone please tell me where I can place sales.xml file? – jhon jhon doe Sep 28 '18 at 08:05
  • place in Sugarcode\Test\etc folder – Pradeep Kumar Sep 28 '18 at 08:07
  • can you give me registration page code so i add in it to run this module – jhon jhon doe Sep 28 '18 at 08:09
  • I copied all the code and make folder and pages but it's not showing anything on cart page so what page or folder I missed please help? – jhon jhon doe Sep 28 '18 at 08:17
  • I want to fetch a price from my custom table and show in cart page please help? – jhon jhon doe Sep 28 '18 at 08:28
  • can you help me in chat ??? appreciated – jhon jhon doe Sep 28 '18 at 08:30
  • Can anyone explaine what happens when an order created? Is just grant total of order changed or are there any entries created for custom price? – iskorum Jun 24 '19 at 13:18
  • Is there any update one the "doubled fee" issue? I did remove the duplicate method call in Block\Sales\Order\Fee and I also added the code snippet from the answer down below. The fee still gets applied twice. – hallleron Jun 27 '19 at 08:36
  • 1
    @hallleron yes you have to just comment $total->setGrandTotal($total->getGrandTotal() + $balance); this line and your problem will be solved – Rutvee Sojitra Jul 25 '19 at 07:39
  • hello , Can you please tell me how extra fee is calculated in order total i want to know @PradeepKumar – Hemangi Patel Dec 13 '19 at 05:55
  • How to use this same concept when we only want to add this extra fee on CASH on delivery – Pramod Feb 21 '20 at 08:04
  • @PradeepKumar how to add discount in admin, admin can enter discount amount and click to apply , discount should show on order total summary section – Vinit Kumar Feb 16 '21 at 11:45
  • is there any simple way to add/remove the price on cart page? just to add/remove a single digit it takes a complete module to perform the task. – VishalParkash Mar 27 '21 at 11:47
  • Hi, I've added an extra fee using this module but I can't see the extra fee on the order view details in customer my account. Can you please help me with this? – Vinod Kumar May 31 '22 at 10:40
  • anyone facing a duplicate issue could check this and update the model https://github.com/bragento/magento2-cash-on-delivery-fee/blob/develop/Model/Total/CashOnDeliveryFee.php – Bahaa Odeh Sep 28 '22 at 07:20
  • Does this module add checkbox on checkout page to select fee.? – Anees Nov 30 '23 at 07:03
5

Based on above answer i developed custom fee extension.

https://github.com/sivajik34/Custom-Fee-Magento2

Siva Kumar Koduru
  • 593
  • 2
  • 9
  • 19
5

please comment

        $total->setGrandTotal($total->getGrandTotal() + $balance);

form app\code\Sugarcode\Test\Model\Total\Fee.php for double custom fee issue

Hope it will help you!!

Rutvee Sojitra
  • 3,881
  • 2
  • 17
  • 55
4

The answer of Pradeep is very helpful, but misses an important point.

The function Sugarcode\Test\Model\Total::collect() is called twice by Magento's Magento\Quote\Model\QuoteTotalsCollector::collect(), once for each address. At that point it creates a combined total that is stored in the quote table. It does not show up in the order, nor on the website in the checkout.

For this reason it is important to collect the fee in only one of times that collect() is called. This can be done by checking if there are any shipped items available:

    $items = $shippingAssignment->getItems();
    if (!count($items)) {
        return $this;
    }

Add this code at the beginning of your variant of Sugarcode\Test\Model\Total::collect()

4

I have used the above code for adding the custom fee. Custom fee is dynamic for each order. So i have save the value in the database.

    <?xml version="1.0" encoding="UTF-8"?>
<schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd">
        <table name="quote" resource="default" engine="innodb">
            <column xsi:type="decimal" name="fee" nullable="true" comment="Custom Tax from webservice"/>
        </table>
        <table name="sales_order" resource="sales" engine="innodb" comment="Sales Order">
            <column xsi:type="decimal" name="fee" nullable="true" comment="Custom Tax from webservice"/>
        </table>
</schema>

Convert the quote to sales using fieldset.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:DataObject/etc/fieldset.xsd"> <scope id="global"> <!-- Copy quote to sale order fields --> <fieldset id="sales_convert_quote"> <field name="fee"> <aspect name="to_order" /> </field> </fieldset> </scope> </config>

Observer to convert quote to sales

    <?php

namespace BA\Vertex\Observer\Frontend\Sales;

class QuoteSubmitBefore implements \Magento\Framework\Event\ObserverInterface {

/**
 * Execute observer
 *
 * @param \Magento\Framework\Event\Observer $observer
 * @return void
 */
public function execute(
    \Magento\Framework\Event\Observer $observer
) {
    try {

        $quote = $observer-&gt;getQuote();
        $order = $observer-&gt;getOrder();
        $order-&gt;setData('fee', $quote-&gt;getData('fee'));

    } catch (\Exception $e) {
        $this-&gt;messageManager-&gt;addErrorMessage($e-&gt;getMessage());
    }
}

}

events.xml

 <?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_model_service_quote_submit_before">
        <observer instance="BA\Vertex\Observer\Frontend\Sales\QuoteSubmitBefore" name="ba_vertex_quote_submit_before"/>
    </event>
</config>

For displaying custom fee in magento admin backend

view/adminhtml/layout/sales_order_view.xml

    <?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>        
        <referenceContainer name="order_totals">
            <block class="BA\Vertex\Block\Sales\Order\Fee" name="fee"/>
        </referenceContainer>
    </body>
</page>

Block class

    <?php
namespace BA\Vertex\Block\Sales\Order;

class Fee extends \Magento\Framework\View\Element\Template { /** * @var Order / protected $_order; /* * @return Order / public function getOrder() { return $this->_order; } /* * Initialize all order totals relates with tax * * @return \Magento\Tax\Block\Sales\Order\Tax */ public function initTotals() { $parent = $this->getParentBlock(); $this->_order = $parent->getOrder(); $fee = new \Magento\Framework\DataObject( [ 'code' => 'fee', 'strong' => false, 'value' => $this->_order->getFee(), 'label' => __('Fee'), ] );

    $parent-&gt;addTotal($fee, 'fee');
    return $this;
}

}

Liz Eipe C
  • 1,286
  • 12
  • 17
2

Everyone who is struggling with 2 times fees issue, try the following code to apply fees in the collect method.

$fee = 10;           
$total->addTotalAmount('fee', $fee);
$total->addBaseTotalAmount('fee', $fee);
$total->setBaseGrandTotal($total->getBaseGrandTotal());

Your collect method should look something like this.

    public function collect(
        \Magento\Quote\Model\Quote $quote,
        \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
        \Magento\Quote\Model\Quote\Address\Total $total
    )
    {
        parent::collect($quote, $shippingAssignment, $total);
        if (!count($shippingAssignment->getItems())) {
            return $this;
        }

            $fee = 10;           
            $total->addTotalAmount('fee', $fee);
            $total->addBaseTotalAmount('fee', $fee);
            $total->setBaseGrandTotal($total->getBaseGrandTotal());
            $quote->setFee($fee);          



        return $this;
    }

Dhimant
  • 111
  • 5