0

Magento 2 version 2.2.2

Steps to set tax rules: Create a configurable product, which has two simple (child) products. Configurable product is set as taxable with 20% tax setup. First simple product is set as taxable with 20% tax setup. Second simple product is set as no tax i.e. 0% tax. Add second product through configurable options to cart.

Actual result: Tax of 20% is being applied in cart for the second simple product.

Expected result: 0% tax should be applied for the second simple product.

How can I modify this to achieve my requirement?

0

I was having the same issue due to UK VAT rules and found several magento bug created on github but no actual fix.

So then while looking for a workaround I have built a module to change the Magento behaviour according to our requirement.

Basically we need to update the definition of mapItem method of class Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector

For that we need to override 2 magento classes i.e. write preference in di.xml

<preference for="Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector" type="VendorName\MagentoChildProductTaxExtend\Preference\Tax\Model\Sales\Total\Quote\CommonTaxCollector"/>
<preference for="Magento\Tax\Model\Sales\Total\Quote\Tax" type="VendorName\MagentoChildProductTaxExtend\Preference\Tax\Model\Sales\Total\Quote\Tax"/>

Now in mapItem method of class VendorName\MagentoChildProductTaxExtend\Preference\Tax\Model\Sales\Total\Quote\CommonTaxCollector in line 211, we need to replace the $item->getProduct()->getTaxClassId() with the child product tax class id.

For that, we can change to these lines of code in our own class -

    $taxClassId = $item->getProduct()->getTaxClassId();
    if($item->getHasChildren()) {
        foreach ($item->getChildren() as $child) {
            $taxClassId = $child->getProduct()->getTaxClassId();
        }
    }
    /** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
    $itemDataObject = $itemDataObjectFactory->create();
    $itemDataObject->setCode($item->getTaxCalculationItemId())
        ->setQuantity($item->getQty())
        ->setTaxClassKey(
            $this->taxClassKeyDataObjectFactory->create()
                ->setType(TaxClassKeyInterface::TYPE_ID)
                //->setValue($item->getProduct()->getTaxClassId())
                ->setValue($taxClassId)
        )
        ->setIsTaxIncluded($priceIncludesTax)
        ->setType(self::ITEM_TYPE_PRODUCT);

Create your own module and add those codes, this works in every tax related section in magento, Tested on Ver 2.2.2

Cheers!!

  • Why are you extending Magento\Tax\Model\Sales\Total\Quote\Tax? you're changing only the code in CommonTaxCollector. – SimoneB Jul 3 '18 at 9:27
  • Hi @SimoneB, due to backward compatibility. My modified method wont be called if we dont extend that class as well – Sandipan S Jul 4 '18 at 4:59
  • Not working on 2.2.7, had no chance to test on other versions. I've overridden only the method (not the all class that is simply extended). Is it supposed to be done that way? – SimoneB Jan 15 at 17:04
1

You can also create a plugin for that

di.xml

<type name="Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector">
    <plugin name="child_tax" type="Vendor\ModuleName\Plugin\ChildTaxClass" sortOrder="1" />
</type>

ChildTaxClass.php

namespace Vendor\ModuleName\Plugin;
class ChildTaxClass
{
/**
 * @var \Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory
 */
private $taxClassKeyDataObjectFactory;

/**
 * ChildTaxClass constructor.
 * @param \Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory
 */
public function __construct(
    \Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory
) {
    $this->taxClassKeyDataObjectFactory = $taxClassKeyDataObjectFactory;
}

/**
 * @param \Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector $subject
 * @param callable $proceed
 * @param \Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory
 * @param \Magento\Quote\Model\Quote\Item\AbstractItem $item
 * @param $priceIncludesTax
 * @param $useBaseCurrency
 * @param null $parentCode
 * @return \Magento\Quote\Model\Quote\Item\AbstractItem|\Magento\Tax\Api\Data\QuoteDetailsItemInterface
 */
public function aroundMapItem(
    \Magento\Tax\Model\Sales\Total\Quote\CommonTaxCollector $subject,
    callable $proceed,
    \Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
    \Magento\Quote\Model\Quote\Item\AbstractItem $item,
    $priceIncludesTax,
    $useBaseCurrency,
    $parentCode = null
) {

    $taxClassId = $item->getProduct()->getTaxClassId();
    if ($item->getHasChildren()) {
        foreach ($item->getChildren() as $child) {
            $taxClassId = $child->getProduct()->getTaxClassId();
        }
    }

    // call method
    /** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $item */
    $item = $proceed(
        $itemDataObjectFactory,
        $item,
        $priceIncludesTax,
        $useBaseCurrency,
        $parentCode
    );

    // Set tax class from child (if available)
    $item->setTaxClassId($taxClassId);
    $item->setTaxClassKey(
        $this->taxClassKeyDataObjectFactory->create()
            ->setType(\Magento\Tax\Api\Data\TaxClassKeyInterface::TYPE_ID)
            ->setValue($taxClassId)
    );
    return $item;
}

}

  • this one worked for me thanks" – SimoneB Jan 21 at 17:41
0

i have the same problem on Magento 1 with UK product, different size have different tax rate.

exemple : Configurable (global 20% tax) - Simple 1 (global 20% tax, but on UK 0% tax) - Simple 2 (global 20% tax, but on UK 20% tax)

in method Mage_Tax_Model_Sales_Total_Quote_Tax::_totalBaseProcessItemTax, dont forget to add a config to disable this functionality

///// BEGIN OLD
//$taxRateRequest->setProductClassId($item->getProduct()->getTaxClassId());
///// BEGIN OLD
///// BEGIN AKOA
$configEnable = Mage::getStoreConfigFlag('tax/calculation/tax_rate_on_simple_enable', $item->getStoreId());
if ($configEnable && $item->getHasChildren()) {
    $children = $item->getChildren();
    foreach ($children as $childItem) {
        $taxRateRequest->setProductClassId($childItem->getProduct()->getTaxClassId());
        break;
    }
} else {
    $taxRateRequest->setProductClassId($item->getProduct()->getTaxClassId());
}
///// BEGIN AKOA

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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