getAssociatedItemCode()) { // Use delta rounding of the product's instead of the weee's $type = $type . $item->getAssociatedItemCode(); } else { $type = $type . $item->getCode(); } return $this->deltaRound($amount, $rate, $direction, $type, $round); } /** * {@inheritdoc} */ protected function calculateWithTaxInPrice(QuoteDetailsItemInterface $item, $quantity, $round = true) { $taxRateRequest = $this->getAddressRateRequest()->setProductClassId( $this->taxClassManagement->getTaxClassId($item->getTaxClassKey()) ); $rate = $this->calculationTool->getRate($taxRateRequest); $storeRate = $storeRate = $this->calculationTool->getStoreRate($taxRateRequest, $this->storeId); // Calculate $priceInclTax $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId); $priceInclTax = $this->calculationTool->round($item->getUnitPrice()); if (!$this->isSameRateAsStore($rate, $storeRate)) { $priceInclTax = $this->calculatePriceInclTax($priceInclTax, $storeRate, $rate, $round); } $uniTax = $this->calculationTool->calcTaxAmount($priceInclTax, $rate, true, false); $deltaRoundingType = self::KEY_REGULAR_DELTA_ROUNDING; if ($applyTaxAfterDiscount) { $deltaRoundingType = self::KEY_TAX_BEFORE_DISCOUNT_DELTA_ROUNDING; } $uniTax = $this->roundAmount($uniTax, $rate, true, $deltaRoundingType, $round, $item); $price = $priceInclTax - $uniTax; //Handle discount $discountTaxCompensationAmount = 0; $discountAmount = $item->getDiscountAmount(); if ($applyTaxAfterDiscount) { //TODO: handle originalDiscountAmount $unitDiscountAmount = $discountAmount / $quantity; $taxableAmount = max($priceInclTax - $unitDiscountAmount, 0); $unitTaxAfterDiscount = $this->calculationTool->calcTaxAmount( $taxableAmount, $rate, true, false ); $unitTaxAfterDiscount = $this->roundAmount( $unitTaxAfterDiscount, $rate, true, self::KEY_REGULAR_DELTA_ROUNDING, $round, $item ); // Set discount tax compensation $unitDiscountTaxCompensationAmount = $uniTax - $unitTaxAfterDiscount; $discountTaxCompensationAmount = $unitDiscountTaxCompensationAmount * $quantity; $uniTax = $unitTaxAfterDiscount; } $rowTax = $uniTax * $quantity; // Calculate applied taxes /** @var \Magento\Tax\Api\Data\AppliedTaxInterface[] $appliedTaxes */ $appliedRates = $this->calculationTool->getAppliedRates($taxRateRequest); $appliedTaxes = $this->getAppliedTaxes($rowTax, $rate, $appliedRates); return $this->taxDetailsItemDataObjectFactory->create() ->setCode($item->getCode()) ->setType($item->getType()) ->setRowTax($rowTax) ->setPrice($price) ->setPriceInclTax($priceInclTax) ->setRowTotal($price * $quantity) ->setRowTotalInclTax($priceInclTax * $quantity) ->setDiscountTaxCompensationAmount($discountTaxCompensationAmount) ->setAssociatedItemCode($item->getAssociatedItemCode()) ->setTaxPercent($rate) ->setAppliedTaxes($appliedTaxes); } /** * {@inheritdoc} */ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $quantity, $round = true) { $taxRateRequest = $this->getAddressRateRequest()->setProductClassId( $this->taxClassManagement->getTaxClassId($item->getTaxClassKey()) ); $rate = $this->calculationTool->getRate($taxRateRequest); $appliedRates = $this->calculationTool->getAppliedRates($taxRateRequest); $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($this->storeId); $discountAmount = $item->getDiscountAmount(); $discountTaxCompensationAmount = 0; // Calculate $price $price = $this->calculationTool->round($item->getUnitPrice()); $unitTaxes = []; $unitTaxesBeforeDiscount = []; $appliedTaxes = []; //Apply each tax rate separately foreach ($appliedRates as $appliedRate) { $taxId = $appliedRate['id']; $taxRate = $appliedRate['percent']; $unitTaxPerRate = $this->calculationTool->calcTaxAmount($price, $taxRate, false, false); $deltaRoundingType = self::KEY_REGULAR_DELTA_ROUNDING; if ($applyTaxAfterDiscount) { $deltaRoundingType = self::KEY_TAX_BEFORE_DISCOUNT_DELTA_ROUNDING; } $unitTaxPerRate = $this->roundAmount($unitTaxPerRate, $taxId, false, $deltaRoundingType, $round, $item); $unitTaxAfterDiscount = $unitTaxPerRate; //Handle discount if ($applyTaxAfterDiscount) { //TODO: handle originalDiscountAmount $unitDiscountAmount = $discountAmount / $quantity; $taxableAmount = max($price - $unitDiscountAmount, 0); $unitTaxAfterDiscount = $this->calculationTool->calcTaxAmount( $taxableAmount, $taxRate, false, false ); $unitTaxAfterDiscount = $this->roundAmount( $unitTaxAfterDiscount, $taxId, false, self::KEY_REGULAR_DELTA_ROUNDING, $round, $item ); } $appliedTaxes[$taxId] = $this->getAppliedTax( $unitTaxAfterDiscount * $quantity, $appliedRate ); $unitTaxes[] = $unitTaxAfterDiscount; $unitTaxesBeforeDiscount[] = $unitTaxPerRate; } $unitTax = array_sum($unitTaxes); $unitTaxBeforeDiscount = array_sum($unitTaxesBeforeDiscount); $rowTax = $unitTax * $quantity; $priceInclTax = $price + $unitTaxBeforeDiscount; return $this->taxDetailsItemDataObjectFactory->create() ->setCode($item->getCode()) ->setType($item->getType()) ->setRowTax($rowTax) ->setPrice($price) ->setPriceInclTax($priceInclTax) ->setRowTotal($price * $quantity) ->setRowTotalInclTax($priceInclTax * $quantity) ->setDiscountTaxCompensationAmount($discountTaxCompensationAmount) ->setAssociatedItemCode($item->getAssociatedItemCode()) ->setTaxPercent($rate) ->setAppliedTaxes($appliedTaxes); } }