123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Tax\Model\Calculation;
- use Magento\Tax\Api\Data\QuoteDetailsItemInterface;
- class UnitBaseCalculator extends AbstractCalculator
- {
- /**
- * {@inheritdoc}
- */
- protected function roundAmount(
- $amount,
- $rate = null,
- $direction = null,
- $type = self::KEY_REGULAR_DELTA_ROUNDING,
- $round = true,
- $item = null
- ) {
- if ($item->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);
- }
- }
|