/** * @param \Magento\Sales\Model\Quote\Address $address * @return $this */ public function collect(\Magento\Sales\Model\Quote\Address $address) { $store = $address->getQuote()->getStore(); $address->setTaxAmount(0); $address->setBaseTaxAmount(0); $address->setAppliedTaxes(array()); $items = $address->getAllItems(); if (!count($items)) { return $this; } $custTaxClassId = $address->getQuote()->getCustomerTaxClassId(); $taxCalculationModel = $this->_calculation; /* @var $taxCalculationModel \Magento\Tax\Model\Calculation */ $request = $taxCalculationModel->getRateRequest($address, $address->getQuote()->getBillingAddress(), $custTaxClassId, $store); foreach ($items as $item) { /** * Child item's tax we calculate for parent */ if ($item->getParentItemId()) { continue; } /** * We calculate parent tax amount as sum of children's tax amounts */ if ($item->getHasChildren() && $item->isChildrenCalculated()) { foreach ($item->getChildren() as $child) { $discountBefore = $item->getDiscountAmount(); $baseDiscountBefore = $item->getBaseDiscountAmount(); $rate = $taxCalculationModel->getRate($request->setProductClassId($child->getProduct()->getTaxClassId())); $child->setTaxPercent($rate); $child->calcTaxAmount(); if ($discountBefore != $item->getDiscountAmount()) { $address->setDiscountAmount($address->getDiscountAmount() + ($item->getDiscountAmount() - $discountBefore)); $address->setBaseDiscountAmount($address->getBaseDiscountAmount() + ($item->getBaseDiscountAmount() - $baseDiscountBefore)); $address->setGrandTotal($address->getGrandTotal() - ($item->getDiscountAmount() - $discountBefore)); $address->setBaseGrandTotal($address->getBaseGrandTotal() - ($item->getBaseDiscountAmount() - $baseDiscountBefore)); } $this->_saveAppliedTaxes($address, $taxCalculationModel->getAppliedRates($request), $child->getTaxAmount(), $child->getBaseTaxAmount(), $rate); } $itemTaxAmount = $item->getTaxAmount() + $item->getDiscountTaxCompensation(); $address->setTaxAmount($address->getTaxAmount() + $itemTaxAmount); $itemBaseTaxAmount = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation(); $address->setBaseTaxAmount($address->getBaseTaxAmount() + $itemBaseTaxAmount); } else { $discountBefore = $item->getDiscountAmount(); $baseDiscountBefore = $item->getBaseDiscountAmount(); $rate = $taxCalculationModel->getRate($request->setProductClassId($item->getProduct()->getTaxClassId())); $item->setTaxPercent($rate); $item->calcTaxAmount(); if ($discountBefore != $item->getDiscountAmount()) { $address->setDiscountAmount($address->getDiscountAmount() + ($item->getDiscountAmount() - $discountBefore)); $address->setBaseDiscountAmount($address->getBaseDiscountAmount() + ($item->getBaseDiscountAmount() - $baseDiscountBefore)); $address->setGrandTotal($address->getGrandTotal() - ($item->getDiscountAmount() - $discountBefore)); $address->setBaseGrandTotal($address->getBaseGrandTotal() - ($item->getBaseDiscountAmount() - $baseDiscountBefore)); } $itemTaxAmount = $item->getTaxAmount() + $item->getDiscountTaxCompensation(); $address->setTaxAmount($address->getTaxAmount() + $itemTaxAmount); $itemBaseTaxAmount = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation(); $address->setBaseTaxAmount($address->getBaseTaxAmount() + $itemBaseTaxAmount); $applied = $taxCalculationModel->getAppliedRates($request); $this->_saveAppliedTaxes($address, $applied, $item->getTaxAmount(), $item->getBaseTaxAmount(), $rate); } } $shippingTaxClass = $this->_scopeConfig->getValue(\Magento\Tax\Model\Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $store); $shippingTax = 0; $shippingBaseTax = 0; if ($shippingTaxClass) { $rate = $taxCalculationModel->getRate($request->setProductClassId($shippingTaxClass)); if ($rate) { if (!$this->_taxData->shippingPriceIncludesTax()) { $shippingTax = $address->getShippingAmount() * $rate / 100; $shippingBaseTax = $address->getBaseShippingAmount() * $rate / 100; } else { $shippingTax = $address->getShippingTaxAmount(); $shippingBaseTax = $address->getBaseShippingTaxAmount(); } $shippingTax = $this->priceCurrency->round($shippingTax); $shippingBaseTax = $this->priceCurrency->round($shippingBaseTax); $address->setTaxAmount($address->getTaxAmount() + $shippingTax); $address->setBaseTaxAmount($address->getBaseTaxAmount() + $shippingBaseTax); $this->_saveAppliedTaxes($address, $taxCalculationModel->getAppliedRates($request), $shippingTax, $shippingBaseTax, $rate); } } if (!$this->_taxData->shippingPriceIncludesTax()) { $address->setShippingTaxAmount($shippingTax); $address->setBaseShippingTaxAmount($shippingBaseTax); } $address->setGrandTotal($address->getGrandTotal() + $address->getTaxAmount()); $address->setBaseGrandTotal($address->getBaseGrandTotal() + $address->getBaseTaxAmount()); return $this; }