2

I had to change prices to 4 decimals and it's OK. However, i have sometimes rounded cent in totals which is wrong. The explanation is that all calculations (subtotal, VAT and total) are on 4 decimals then rounded to 2 decimals. With rounding, subtotal + VAT is sometimes different for 1 cent from total.

To fix this, i need to :

  • keep product prices to 4 decimals
  • keep subtotal calculate on 4 decimals then rounded it to 2 decimals
  • calculate VAT and total from this rounded subtotal and not from the 4 decimals subtotal.

But i can't figure how to do this. I tried multiple solutions and nothing is working : even with forcing subtotal/VAT and saving, it seems to be calculated again elsewhere and 4 decimals appear again.

Can you give me some piece of advice on how to achieve this ? Thanks !

Aurel
  • 338
  • 2
  • 13

1 Answers1

-2

I succeed in rewriting event sales_quote_collect_totals_after

Update : here is the code

in Myvendor/Mymodule/etc/events.xml :

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_quote_address_collect_totals_after">
        <observer name="changeTotals" instance="Myvendor\Mymodule\Observer\ChangeTotals"/>
    </event>
</config>

In Myvendor/Mymodule/Observer/ChangeTotals.php :

<?php
namespace Myvendor\Mymodule\Observer;

use Psr\Log\LoggerInterface as Logger;
use \Magento\Framework\Event\ObserverInterface;
use \Magento\Framework\Event\Observer;

class ChangeTotals implements ObserverInterface
{
     /**
     * @var Logger
     */
    protected $_logger;
    
    /**
     * [__construct ]
     * 
     * @param Logger $logger
     */
    public function __construct(
        Logger $logger
    ) {
        $this->_logger = $logger;
    }

    public function execute(Observer $observer)
    {
        /** @var Magento\Quote\Model\Quote\Address\Total */
        $total = $observer->getData('total');
        
            $subtotal = $total->getTotalAmount('subtotal');
            $tax = $total->getTotalAmount('tax');
            $grandTotal = $total->getGrandTotal();
            
            /* $this->_logger->info('**** total_before **** ' , array($total->getData()));*/
            
            /* the $total->getData() contains : 
            [subtotal] => 0
            [weee] => 0
            [discount] => 0
            [shipping] => 0
            [shipping_discount] => 0
            [tax] => 0
            [discount_tax_compensation] => 0
            [shipping_discount_tax_compensation] => 0
            [extra_tax] => 0
            [weee_tax] => 0*/
            
            // i round tax to 2 decimals
            $tax = round($tax,2);
            $total->setTotalAmount('tax', $tax);
            $total->setBaseTaxAmount($tax);
            
            /* recalculate grandTotal */
            $grandTotal = round($subtotal,2) + $tax + $total->getTotalAmount('discount') + $total->getShippingAmount()
            +$total->getShippingDiscountAmount() + $total->getDiscountTaxCompensation() + $total->getShippingDiscountTaxCompensation() + $total->getExtraTax(), 2);

            /* recalculate baseGrandTotal */
            $baseGrandTotal = round($total->getBaseSubtotal(),2) + $tax + $total->getBaseDiscount() + $total->getBaseShippingAmount()
            + $total->getBaseShippingDiscountAmount() + $total->getBaseDiscountTaxCompensation() + $total->getBaseShippingDiscountTaxCompensation() + $total->getBaseExtraTax(), 2);
            /* update totals */
            $total->setGrandTotal($grandTotal);
            /*$total->setBaseGrandTotal($baseGrandTotal);

            /* $this->_logger->info('**** total_after **** ' , array($total->getData())); */

        return $this;
    }
}
Aurel
  • 338
  • 2
  • 13