Search code examples
phpmagentomagento-1.6gomage

Magento: tax wrong on extra fee in checkout


I've added an extra fee to my checkout and but the tax isn't calculated correctly.

The amount of tax is not added up correctly, if I do $this->_calculateTax($address); in the collect function it is added up to the total including tax but my amount of tax is still of then.

if is var_dump the set applied taxes after the line $address->setAppliedTaxes($previouslyAppliedTaxes); I do see the correct amount. It dumps this twice, the first time I see the correct amount of tax of just my extra fee, the second the correct amount of total tax. But in the frontend it shows the tax without the tax of my extra fee.

Any clue on what this could be?

    class Company_Customer_Model_Quote_Address_Total_PrintPrepCosts extends Mage_Sales_Model_Quote_Address_Total_Abstract
{
    public function __construct() {
        $this->setCode('printPrepCosts');
        $this->_store = Mage::app()->getStore();
        return $this;
    }

public function collect(Mage_Sales_Model_Quote_Address $address)
    {
        parent::collect($address);
        $address->setPrintPrepcosts(0);
        $address->setTaxAmount(0);
        $address->setBaseTaxAmount(0);

        if(count($address->getAllItems()) == 0)
        {
            return $this;
        }

        $pricePrint = $this->calcTotalPrintPrepCosts();

        $address->setPrintPrepcosts($pricePrint);
        $address->setBasePrintPrepcosts($pricePrint);

        $address->setBaseGrandTotal($address->getBaseGrandTotal() + $address->getPrintPrepcosts());
        $address->setGrandTotal($address->getGrandTotal() + $address->getPrintPrepcosts());

        $this->_calculateTax($address);
        return $this;
    }

    protected function _calculateTax(Mage_Sales_Model_Quote_Address $address)
    {
        $calculator     = Mage::getSingleton('tax/calculation');
        $inclTax        = Mage::getStoreConfig('tax/calculation/printing_prep_includes_tax', $this->_store);

        $taxRateRequest = $calculator->getRateRequest(
            $address,
            $address->getQuote()->getBillingAddress(),
            $address->getQuote()->getCustomerTaxClassId(),
            $this->_store
        );

        // TODO undef prop _store
        $taxRateRequest->setProductClassId(Mage::getStoreConfig('tax/classes/printing_prep_tax_class', $this->_store));

        $rate = $calculator->getRate($taxRateRequest);
        $baseTax = $tax = $calculator->calcTaxAmount($address->getPrepPrintcosts(), $rate, $inclTax, true);

        $address->addTotalAmount('tax', max(0, $tax));
        $address->addBaseTotalAmount('tax', max(0, $baseTax));

        $this->_saveAppliedTaxes($address, 
            $calculator->getAppliedRates($taxRateRequest), 
            $tax, 
            $baseTax, 
            $rate
        );

        // later on added - which fixes the total, lose tax amount still off
        $address->setTaxAmount($tax);
        $address->setBaseTaxAmount($baseTax);

        if($inclTax)
        {
            $address->setBaseGrandTotal($address->getBaseGrandTotal() - $baseTax);
            $address->setGrandTotal($address->getGrandTotal() - $tax);
        }
    }

    protected function _saveAppliedTaxes(Mage_Sales_Model_Quote_Address $address, $applied, $amount, $baseAmount, $rate)
    {
        $previouslyAppliedTaxes = $address->getAppliedTaxes();
        $process = count($previouslyAppliedTaxes);


        foreach ($applied as $row) {
            if (!isset($previouslyAppliedTaxes[$row['id']])) {
                $row['process'] = $process;
                $row['amount'] = 0;
                $row['base_amount'] = 0;
                $previouslyAppliedTaxes[$row['id']] = $row;
            }

            if (!is_null($row['percent'])) {
                $row['percent'] = $row['percent'] ? $row['percent'] : 1;
                $rate = $rate ? $rate : 1;

                $appliedAmount = $amount/$rate*$row['percent'];
                $baseAppliedAmount = $baseAmount/$rate*$row['percent'];
            } else {
                $appliedAmount = 0;
                $baseAppliedAmount = 0;
                foreach ($row['rates'] as $rate) {
                    $appliedAmount += $rate['amount'];
                    $baseAppliedAmount += $rate['base_amount'];
                }
            }


            if ($appliedAmount || $previouslyAppliedTaxes[$row['id']]['amount']) {
                $previouslyAppliedTaxes[$row['id']]['amount'] += $appliedAmount;
                $previouslyAppliedTaxes[$row['id']]['base_amount'] += $baseAppliedAmount;
            } else {
                unset($previouslyAppliedTaxes[$row['id']]);
            }
        }
        $address->setAppliedTaxes($previouslyAppliedTaxes);        
    }

    public function fetch(Mage_Sales_Model_Quote_Address $address)
    {
        $address->addTotal(array(
            'code'  => $this->getCode(),
            'title' => "Prep Print costs",
            'value' => $address->getPrintPrepcosts(),
        ));
        return $this;
    }

EDIT 1 XML contains this:

        <sales>
        <quote>
            <totals>
                <printPrepCosts>
                    <class>Company_Customer_Model_Quote_Address_Total_PrintPrepCosts</class>
                    <after>subtotal</after>
                    <before>tax</before>
                </printPrepCosts>
            </totals>
        </quote>
    </sales>

EDIT 2 I have added the following lines to my calcTax function, this does fix the grand total but the amount of TAX is still off.

  $address->setTaxAmount($tax);
  $address->setBaseTaxAmount($baseTax);

OUTPUT - example

Subtotal    € 67,50
printPrepCosts  € 40,00
Shipping    € 50,00
TAX     € 22,33
Total   € 187,43

EDIT 3 My bad, only the GoMage onepage checkout gives the correct grand total, the cart doesn't. The regular Magento onepage checkout gives the wrong grandtotal as well.


Solution

  • I found a workaround, it isn't the best solution but it does work :)

    In my address I will set the tax to an extra var called tax and use that in the observer to manipulate the tax.

    class Company_Client_Model_Observer
    {   
        public function setCorrectTax ($observer)
        {
            $quote = $observer->getQuote();
            foreach ($quote->getAllAddresses() as $address) {
                $printPrepCosts = $address->getPrintPrepcosts();
                if(!empty($printPrepCosts)) {
                    $address->setTaxAmount($address->tax);
                }
            }
        }
    }
    

    And the XML

        <events>
        <sales_quote_collect_totals_after>
            <observers>
                <client>
                    <type>singleton</type>
                    <class>client/observer</class>
                    <method>setCorrectTax</method>
                </client>
            </observers>
        </sales_quote_collect_totals_after>
        </events>