Example #1
1
 /**
  * Check if tax amount should be included to grandtotal block
  * array(
  *  $index => array(
  *      'amount'   => $amount,
  *      'label'    => $label,
  *      'font_size'=> $font_size
  *  )
  * )
  * @return array
  */
 public function getTotalsForDisplay()
 {
     $store = $this->getOrder()->getStore();
     if ($this->_taxConfig->displaySalesTaxWithGrandTotal($store)) {
         return [];
     }
     $totals = [];
     if ($this->_taxConfig->displaySalesFullSummary($store)) {
         $totals = $this->getFullTaxInfo();
     }
     $totals = array_merge($totals, parent::getTotalsForDisplay());
     return $totals;
 }
 /**
  * Check if tax amount should be included to grandtotals block
  * array(
  *  $index => array(
  *      'amount'   => $amount,
  *      'label'    => $label,
  *      'font_size'=> $font_size
  *  )
  * )
  * @return array
  */
 public function getTotalsForDisplay()
 {
     $store = $this->getOrder()->getStore();
     if (!$this->_taxConfig->displaySalesTaxWithGrandTotal($store)) {
         return parent::getTotalsForDisplay();
     }
     $amount = $this->getOrder()->formatPriceTxt($this->getAmount());
     $amountExclTax = $this->getAmount() - $this->getSource()->getTaxAmount();
     $amountExclTax = $amountExclTax > 0 ? $amountExclTax : 0;
     $amountExclTax = $this->getOrder()->formatPriceTxt($amountExclTax);
     $tax = $this->getOrder()->formatPriceTxt($this->getSource()->getTaxAmount());
     $fontSize = $this->getFontSize() ? $this->getFontSize() : 7;
     $totals = [['amount' => $this->getAmountPrefix() . $amountExclTax, 'label' => __('Grand Total (Excl. Tax)') . ':', 'font_size' => $fontSize]];
     if ($this->_taxConfig->displaySalesFullSummary($store)) {
         $totals = array_merge($totals, $this->getFullTaxInfo());
     }
     $totals[] = ['amount' => $this->getAmountPrefix() . $tax, 'label' => __('Tax') . ':', 'font_size' => $fontSize];
     $totals[] = ['amount' => $this->getAmountPrefix() . $amount, 'label' => __('Grand Total (Incl. Tax)') . ':', 'font_size' => $fontSize];
     return $totals;
 }
 /**
  * @param array $addressData
  * @param bool $useBaseCurrency
  * @param string $shippingTaxClass
  * @param bool shippingPriceInclTax
  * @param array $expectedValue
  * @dataProvider getShippingDataObjectDataProvider
  */
 public function testGetShippingDataObject(array $addressData, $useBaseCurrency, $shippingTaxClass, $shippingPriceInclTax)
 {
     $baseShippingAmount = $addressData['base_shipping_amount'];
     $shippingAmount = $addressData['shipping_amount'];
     $itemMock = $this->getMock('Magento\\Tax\\Api\\Data\\QuoteDetailsItemInterface');
     $this->taxConfig->expects($this->any())->method('getShippingTaxClass')->with($this->store)->will($this->returnValue($shippingTaxClass));
     $this->taxConfig->expects($this->any())->method('shippingPriceIncludesTax')->with($this->store)->will($this->returnValue($shippingPriceInclTax));
     $this->address->expects($this->atLeastOnce())->method('getShippingDiscountAmount')->willReturn($shippingAmount);
     if ($shippingAmount) {
         if ($useBaseCurrency && $shippingAmount != 0) {
             $this->address->expects($this->once())->method('getBaseShippingDiscountAmount')->willReturn($baseShippingAmount);
             $this->quoteDetailsItemBuilderMock->expects($this->once())->method('setDiscountAmount')->with($baseShippingAmount);
         } else {
             $this->address->expects($this->never())->method('getBaseShippingDiscountAmount');
             $this->quoteDetailsItemBuilderMock->expects($this->once())->method('setDiscountAmount')->with($shippingAmount);
         }
     }
     foreach ($addressData as $key => $value) {
         $this->address->setData($key, $value);
     }
     $this->taxClassKeyBuilderMock->expects($this->any())->method('setType')->willReturnSelf();
     $this->taxClassKeyBuilderMock->expects($this->any())->method('setValue')->with($shippingTaxClass)->willReturnSelf();
     $this->quoteDetailsItemBuilderMock->expects($this->once())->method('create')->willReturn($itemMock);
     $this->assertEquals($itemMock, $this->commonTaxCollector->getShippingDataObject($this->address, $useBaseCurrency));
 }
Example #4
0
 /**
  * Check if we need display both sobtotals
  *
  * @return bool
  */
 public function displayBoth()
 {
     /**
      * Check without store parameter - we wil get admin configuration value
      */
     return $this->_taxConfig->displayCartSubtotalBoth();
 }
 /**
  * @param \Magento\Quote\Model\Cart\TotalsConverter $subject
  * @param \Closure $proceed
  * @param \Magento\Quote\Model\Quote\Address\Total[] $addressTotals
  * @return \Magento\Quote\Api\Data\TotalSegmentInterface[]
  * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  */
 public function aroundProcess(\Magento\Quote\Model\Cart\TotalsConverter $subject, \Closure $proceed, array $addressTotals = [])
 {
     $totalSegments = $proceed($addressTotals);
     if (!array_key_exists($this->code, $addressTotals)) {
         return $totalSegments;
     }
     $taxes = $addressTotals['tax']->getData();
     if (!array_key_exists('full_info', $taxes)) {
         return $totalSegments;
     }
     $detailsId = 1;
     $finalData = [];
     foreach (unserialize($taxes['full_info']) as $info) {
         if (array_key_exists('hidden', $info) && $info['hidden'] || $info['amount'] == 0 && $this->taxConfig->displayCartZeroTax()) {
             continue;
         }
         $taxDetails = $this->detailsFactory->create([]);
         $taxDetails->setAmount($info['amount']);
         $taxRates = $this->getRatesData($info['rates']);
         $taxDetails->setRates($taxRates);
         $taxDetails->setGroupId($detailsId);
         $finalData[] = $taxDetails;
         $detailsId++;
     }
     $attributes = $totalSegments[$this->code]->getExtensionAttributes();
     if ($attributes === null) {
         $attributes = $this->totalSegmentExtensionFactory->create();
     }
     $attributes->setTaxGrandtotalDetails($finalData);
     $totalSegments[$this->code]->setExtensionAttributes($attributes);
     return $totalSegments;
 }
Example #6
0
 /**
  * Check if we have include tax amount between grandtotal incl/excl tax
  *
  * @return bool
  */
 public function includeTax()
 {
     if ($this->getTotal()->getValue()) {
         return $this->_taxConfig->displayCartTaxWithGrandTotal($this->getStore());
     }
     return false;
 }
Example #7
0
 /**
  * Tests the getCalculationSequence method
  *
  * @param bool $applyTaxAfterDiscount
  * @param bool $discountTaxIncl
  * @param string $expectedValue
  * @dataProvider dataProviderGetCalculationSequence
  */
 public function testGetCalculationSequence($applyTaxAfterDiscount, $discountTaxIncl, $expectedValue)
 {
     $scopeConfigMock = $this->getMockForAbstractClass('Magento\\Framework\\App\\Config\\ScopeConfigInterface');
     $scopeConfigMock->expects($this->at(0))->method('getValue')->will($this->returnValue($applyTaxAfterDiscount));
     $scopeConfigMock->expects($this->at(1))->method('getValue')->will($this->returnValue($discountTaxIncl));
     /** @var \Magento\Tax\Model\Config */
     $model = new Config($scopeConfigMock);
     $this->assertEquals($expectedValue, $model->getCalculationSequence());
 }
Example #8
0
 /**
  * @param array $addressData
  * @param bool $useBaseCurrency
  * @param string $shippingTaxClass
  * @param bool shippingPriceInclTax
  * @param array $expectedValue
  * @dataProvider getShippingDataObjectDataProvider
  */
 public function testGetShippingDataObject(array $addressData, $useBaseCurrency, $shippingTaxClass, $shippingPriceInclTax, array $expectedValue)
 {
     $this->taxConfig->expects($this->any())->method('getShippingTaxClass')->with($this->store)->will($this->returnValue($shippingTaxClass));
     $this->taxConfig->expects($this->any())->method('shippingPriceIncludesTax')->with($this->store)->will($this->returnValue($shippingPriceInclTax));
     foreach ($addressData as $key => $value) {
         $this->address->setData($key, $value);
     }
     $shippingDataObject = $this->commonTaxCollector->getShippingDataObject($this->address, $useBaseCurrency);
     $this->assertEquals($expectedValue, $shippingDataObject->__toArray());
     //call it again, make sure we get the same output
     $shippingDataObject = $this->commonTaxCollector->getShippingDataObject($this->address, $useBaseCurrency);
     $this->assertEquals($expectedValue, $shippingDataObject->__toArray());
 }
 /**
  * @param array $addressData
  * @param bool $useBaseCurrency
  * @param string $shippingTaxClass
  * @param bool $shippingPriceInclTax
  * @dataProvider getShippingDataObjectDataProvider
  */
 public function testGetShippingDataObject(array $addressData, $useBaseCurrency, $shippingTaxClass, $shippingPriceInclTax)
 {
     $shippingAssignmentMock = $this->getMock('Magento\\Quote\\Api\\Data\\ShippingAssignmentInterface');
     $methods = ['getShippingDiscountAmount', 'getShippingTaxCalculationAmount', 'setShippingTaxCalculationAmount', 'getShippingAmount', 'setBaseShippingTaxCalculationAmount', 'getBaseShippingAmount', 'getBaseShippingDiscountAmount'];
     $totalsMock = $this->getMock('Magento\\Quote\\Model\\Quote\\Address\\Total', $methods, [], '', false);
     $shippingMock = $this->getMock('Magento\\Quote\\Api\\Data\\ShippingInterface');
     $shippingAssignmentMock->expects($this->once())->method('getShipping')->willReturn($shippingMock);
     $shippingMock->expects($this->once())->method('getAddress')->willReturn($this->address);
     $baseShippingAmount = $addressData['base_shipping_amount'];
     $shippingAmount = $addressData['shipping_amount'];
     $totalsMock->expects($this->any())->method('getShippingTaxCalculationAmount')->willReturn($shippingAmount);
     $this->taxConfig->expects($this->any())->method('getShippingTaxClass')->with($this->store)->will($this->returnValue($shippingTaxClass));
     $this->taxConfig->expects($this->any())->method('shippingPriceIncludesTax')->with($this->store)->will($this->returnValue($shippingPriceInclTax));
     $totalsMock->expects($this->atLeastOnce())->method('getShippingDiscountAmount')->willReturn($shippingAmount);
     if ($shippingAmount) {
         if ($useBaseCurrency && $shippingAmount != 0) {
             $totalsMock->expects($this->once())->method('getBaseShippingDiscountAmount')->willReturn($baseShippingAmount);
             $expectedDiscountAmount = $baseShippingAmount;
         } else {
             $totalsMock->expects($this->never())->method('getBaseShippingDiscountAmount');
             $expectedDiscountAmount = $shippingAmount;
         }
     }
     foreach ($addressData as $key => $value) {
         $totalsMock->setData($key, $value);
     }
     $this->assertEquals($this->quoteDetailsItemDataObject, $this->commonTaxCollector->getShippingDataObject($shippingAssignmentMock, $totalsMock, $useBaseCurrency));
     if ($shippingAmount) {
         $this->assertEquals($expectedDiscountAmount, $this->quoteDetailsItemDataObject->getDiscountAmount());
     }
 }
Example #10
0
 /**
  * Add tax totals information to address object
  *
  * @param   Address $address
  * @return  $this
  * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  */
 public function fetch(Address $address)
 {
     $applied = $address->getAppliedTaxes();
     $store = $address->getQuote()->getStore();
     $amount = $address->getTaxAmount();
     $items = $this->_getAddressItems($address);
     $discountTaxCompensation = 0;
     foreach ($items as $item) {
         $discountTaxCompensation += $item->getDiscountTaxCompensation();
     }
     $taxAmount = $amount + $discountTaxCompensation;
     $area = null;
     if ($this->_config->displayCartTaxWithGrandTotal($store) && $address->getGrandTotal()) {
         $area = 'taxes';
     }
     if ($amount != 0 || $this->_config->displayCartZeroTax($store)) {
         $address->addTotal(['code' => $this->getCode(), 'title' => __('Tax'), 'full_info' => $applied ? $applied : [], 'value' => $amount, 'area' => $area]);
     }
     $store = $address->getQuote()->getStore();
     /**
      * Modify subtotal
      */
     if ($this->_config->displayCartSubtotalBoth($store) || $this->_config->displayCartSubtotalInclTax($store)) {
         if ($address->getSubtotalInclTax() > 0) {
             $subtotalInclTax = $address->getSubtotalInclTax();
         } else {
             $subtotalInclTax = $address->getSubtotal() + $taxAmount - $address->getShippingTaxAmount();
         }
         $address->addTotal(['code' => 'subtotal', 'title' => __('Subtotal'), 'value' => $subtotalInclTax, 'value_incl_tax' => $subtotalInclTax, 'value_excl_tax' => $address->getSubtotal()]);
     }
     return $this;
 }
Example #11
0
 /**
  * Add tax totals information to address object
  *
  * @param \Magento\Quote\Model\Quote $quote
  * @param Address\Total $total
  * @return array|null
  * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  * @SuppressWarnings(PHPMD.NPathComplexity)
  */
 public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total)
 {
     $totals = [];
     $store = $quote->getStore();
     $applied = $total->getAppliedTaxes();
     if (is_string($applied)) {
         $applied = unserialize($applied);
     }
     $amount = $total->getTaxAmount();
     if ($amount == null) {
         $this->enhanceTotalData($quote, $total);
         $amount = $total->getTaxAmount();
     }
     $taxAmount = $amount + $total->getTotalAmount('discount_tax_compensation');
     $area = null;
     if ($this->_config->displayCartTaxWithGrandTotal($store) && $total->getGrandTotal()) {
         $area = 'taxes';
     }
     $totals[] = ['code' => $this->getCode(), 'title' => __('Tax'), 'full_info' => $applied ? $applied : [], 'value' => $amount, 'area' => $area];
     /**
      * Modify subtotal
      */
     if ($this->_config->displayCartSubtotalBoth($store) || $this->_config->displayCartSubtotalInclTax($store)) {
         if ($total->getSubtotalInclTax() > 0) {
             $subtotalInclTax = $total->getSubtotalInclTax();
         } else {
             $subtotalInclTax = $total->getSubtotal() + $taxAmount - $total->getShippingTaxAmount();
         }
         $totals[] = ['code' => 'subtotal', 'title' => __('Subtotal'), 'value' => $subtotalInclTax, 'value_incl_tax' => $subtotalInclTax, 'value_excl_tax' => $total->getSubtotal()];
     }
     if (empty($totals)) {
         return null;
     }
     return $totals;
 }
 /**
  * @param CartTotalRepository $subject
  * @param \Closure $proceed
  * @param int $cartId
  * @return \Magento\Quote\Model\Cart\Totals
  * @throws \Magento\Framework\Exception\NoSuchEntityException
  * @SuppressWarnings(PHPMD.UnusedFormalParameter)
  */
 public function aroundGet(CartTotalRepository $subject, \Closure $proceed, $cartId)
 {
     $result = $proceed($cartId);
     $quote = $this->quoteRepository->getActive($cartId);
     $totals = $quote->getTotals();
     if (!array_key_exists('tax', $totals)) {
         return $result;
     }
     $taxes = $totals['tax']->getData();
     if (!array_key_exists('full_info', $taxes)) {
         return $result;
     }
     $detailsId = 1;
     $finalData = [];
     foreach ($taxes['full_info'] as $info) {
         if (array_key_exists('hidden', $info) && $info['hidden'] || $info['amount'] == 0 && $this->taxConfig->displayCartZeroTax()) {
             continue;
         }
         $taxDetails = $this->detailsFactory->create([]);
         $taxDetails->setAmount($info['amount']);
         $taxRates = $this->getRatesData($info['rates']);
         $taxDetails->setRates($taxRates);
         $taxDetails->setGroupId($detailsId);
         $finalData[] = $taxDetails;
         $detailsId++;
     }
     $attributes = $result->getExtensionAttributes();
     if ($attributes === null) {
         $attributes = $this->extensionFactory->create();
     }
     $attributes->setTaxGrandtotalDetails($finalData);
     /** @var $result \Magento\Quote\Model\Cart\Totals */
     $result->setExtensionAttributes($attributes);
     return $result;
 }
Example #13
0
 /**
  * Build message text
  * Determine which notification and data to display
  *
  * @return string
  */
 public function getText()
 {
     $messageDetails = '';
     if (!empty($this->storesWithInvalidDisplaySettings) && !$this->taxConfig->isWrongDisplaySettingsIgnored()) {
         $messageDetails .= '<strong>';
         $messageDetails .= __('Warning tax configuration can result in rounding errors. ');
         $messageDetails .= '</strong><br>';
         $messageDetails .= __('Store(s) affected: ');
         $messageDetails .= implode(', ', $this->storesWithInvalidDisplaySettings);
         $messageDetails .= '<br><div style="text-align:right">';
         $messageDetails .= __('Click on the link to <a href="%1">ignore this notification</a>', $this->getIgnoreTaxNotificationUrl('price_display'));
         $messageDetails .= "</div><br>";
     }
     if (!empty($this->storesWithInvalidDiscountSettings) && !$this->taxConfig->isWrongDiscountSettingsIgnored()) {
         $messageDetails .= '<strong>';
         $messageDetails .= __('Warning tax discount configuration might result in different discounts
                             than a customer might expect. ');
         $messageDetails .= '</strong><br>';
         $messageDetails .= __('Store(s) affected: ');
         $messageDetails .= implode(', ', $this->storesWithInvalidDiscountSettings);
         $messageDetails .= '<br><div style="text-align:right">';
         $messageDetails .= __('Click on the link to <a href="%1">ignore this notification</a>', $this->getIgnoreTaxNotificationUrl('discount'));
         $messageDetails .= "</div><br>";
     }
     $messageDetails .= '<br>';
     $messageDetails .= __('Please see <a href="%1">documentation</a> for more details. ', $this->getInfoUrl());
     $messageDetails .= __('Click here to go to <a href="%1">Tax Configuration</a> and change your settings.', $this->getManageUrl());
     return $messageDetails;
 }
 /**
  * Check if tax rate is same as store tax rate
  *
  * @param float $rate
  * @param float $storeRate
  * @return bool
  */
 protected function isSameRateAsStore($rate, $storeRate)
 {
     if ((bool) $this->config->crossBorderTradeEnabled($this->storeId)) {
         return true;
     } else {
         return abs($rate - $storeRate) < 1.0E-5;
     }
 }
Example #15
0
 /**
  * Get array of arrays with totals information for display in PDF
  * array(
  *  $index => array(
  *      'amount'   => $amount,
  *      'label'    => $label,
  *      'font_size'=> $font_size
  *  )
  * )
  * @return array
  */
 public function getTotalsForDisplay()
 {
     $store = $this->getOrder()->getStore();
     $amount = $this->getOrder()->formatPriceTxt($this->getAmount());
     $amountInclTax = $this->getSource()->getShippingInclTax();
     if (!$amountInclTax) {
         $amountInclTax = $this->getAmount() + $this->getSource()->getShippingTaxAmount();
     }
     $amountInclTax = $this->getOrder()->formatPriceTxt($amountInclTax);
     $fontSize = $this->getFontSize() ? $this->getFontSize() : 7;
     if ($this->_taxConfig->displaySalesShippingBoth($store)) {
         $totals = [['amount' => $this->getAmountPrefix() . $amount, 'label' => __('Shipping (Excl. Tax)') . ':', 'font_size' => $fontSize], ['amount' => $this->getAmountPrefix() . $amountInclTax, 'label' => __('Shipping (Incl. Tax)') . ':', 'font_size' => $fontSize]];
     } elseif ($this->_taxConfig->displaySalesShippingInclTax($store)) {
         $totals = [['amount' => $this->getAmountPrefix() . $amountInclTax, 'label' => __($this->getTitle()) . ':', 'font_size' => $fontSize]];
     } else {
         $totals = [['amount' => $this->getAmountPrefix() . $amount, 'label' => __($this->getTitle()) . ':', 'font_size' => $fontSize]];
     }
     return $totals;
 }
Example #16
0
 /**
  * Get label for shipping total based on configuration settings
  *
  * @return string
  */
 public function getShippingLabel()
 {
     $source = $this->getSource();
     if ($this->_taxConfig->displaySalesShippingInclTax($source->getOrder()->getStoreId())) {
         $label = __('Refund Shipping (Incl. Tax)');
     } elseif ($this->_taxConfig->displaySalesShippingBoth($source->getOrder()->getStoreId())) {
         $label = __('Refund Shipping (Excl. Tax)');
     } else {
         $label = __('Refund Shipping');
     }
     return $label;
 }
 /**
  * @param array $addressData
  * @param bool $useBaseCurrency
  * @param string $shippingTaxClass
  * @param bool $shippingPriceInclTax
  * @dataProvider getShippingDataObjectDataProvider
  */
 public function testGetShippingDataObject(array $addressData, $useBaseCurrency, $shippingTaxClass, $shippingPriceInclTax)
 {
     $baseShippingAmount = $addressData['base_shipping_amount'];
     $shippingAmount = $addressData['shipping_amount'];
     $this->taxConfig->expects($this->any())->method('getShippingTaxClass')->with($this->store)->will($this->returnValue($shippingTaxClass));
     $this->taxConfig->expects($this->any())->method('shippingPriceIncludesTax')->with($this->store)->will($this->returnValue($shippingPriceInclTax));
     $this->address->expects($this->atLeastOnce())->method('getShippingDiscountAmount')->willReturn($shippingAmount);
     if ($shippingAmount) {
         if ($useBaseCurrency && $shippingAmount != 0) {
             $this->address->expects($this->once())->method('getBaseShippingDiscountAmount')->willReturn($baseShippingAmount);
             $expectedDiscountAmount = $baseShippingAmount;
         } else {
             $this->address->expects($this->never())->method('getBaseShippingDiscountAmount');
             $expectedDiscountAmount = $shippingAmount;
         }
     }
     foreach ($addressData as $key => $value) {
         $this->address->setData($key, $value);
     }
     $this->assertEquals($this->quoteDetailsItemDataObject, $this->commonTaxCollector->getShippingDataObject($this->address, $useBaseCurrency));
     if ($shippingAmount) {
         $this->assertEquals($expectedDiscountAmount, $this->quoteDetailsItemDataObject->getDiscountAmount());
     }
 }
 /**
  * Update tax related fields for shipping
  *
  * @param QuoteAddress $address
  * @param TaxDetailsItemInterface $shippingTaxDetails
  * @param TaxDetailsItemInterface $baseShippingTaxDetails
  * @return $this
  */
 protected function processShippingTaxInfo(QuoteAddress $address, $shippingTaxDetails, $baseShippingTaxDetails)
 {
     $address->setTotalAmount('shipping', $shippingTaxDetails->getRowTotal());
     $address->setBaseTotalAmount('shipping', $baseShippingTaxDetails->getRowTotal());
     $address->setTotalAmount('shipping_hidden_tax', $shippingTaxDetails->getDiscountTaxCompensationAmount());
     $address->setBaseTotalAmount('shipping_hidden_tax', $baseShippingTaxDetails->getDiscountTaxCompensationAmount());
     $address->setShippingInclTax($shippingTaxDetails->getRowTotalInclTax());
     $address->setBaseShippingInclTax($baseShippingTaxDetails->getRowTotalInclTax());
     $address->setShippingTaxAmount($shippingTaxDetails->getRowTax());
     $address->setBaseShippingTaxAmount($baseShippingTaxDetails->getRowTax());
     //Add the shipping tax to total tax amount
     $address->addTotalAmount('tax', $shippingTaxDetails->getRowTax());
     $address->addBaseTotalAmount('tax', $baseShippingTaxDetails->getRowTax());
     if ($this->_config->discountTax($address->getQuote()->getStore())) {
         $address->setShippingAmountForDiscount($shippingTaxDetails->getRowTotalInclTax());
         $address->setBaseShippingAmountForDiscount($baseShippingTaxDetails->getRowTotalInclTax());
     }
     return $this;
 }
Example #19
0
 /**
  * situation: The admin user specified the desired refund amount that has taxes embedded within it
  *
  * @throws \Magento\Framework\Exception\LocalizedException
  */
 public function testCollectUsingTaxInclShippingAmount()
 {
     $this->taxConfig->expects($this->any())->method('displaySalesShippingInclTax')->willReturn(true);
     $orderShippingAmount = 15;
     $shippingTaxAmount = 3;
     $orderShippingInclTax = $orderShippingAmount + $shippingTaxAmount;
     $orderShippingAmountRefunded = 5;
     $shippingTaxRefunded = 1;
     $refundedInclTax = $orderShippingAmountRefunded + $shippingTaxRefunded;
     $currencyMultiple = 2;
     $baseOrderShippingAmount = $orderShippingAmount * $currencyMultiple;
     $baseShippingTaxAmount = $shippingTaxAmount * $currencyMultiple;
     $baseOrderShippingInclTax = $orderShippingInclTax * $currencyMultiple;
     $baseOrderShippingAmountRefunded = $orderShippingAmountRefunded * $currencyMultiple;
     $baseShippingTaxRefunded = $shippingTaxRefunded * $currencyMultiple;
     $baseRefundedInclTax = $refundedInclTax * $currencyMultiple;
     //determine expected amounts
     $desiredRefundAmount = $baseOrderShippingInclTax - $baseRefundedInclTax;
     $expectedShippingAmount = $orderShippingAmount - $orderShippingAmountRefunded;
     $expectedShippingAmountInclTax = $orderShippingInclTax - $refundedInclTax;
     $expectedBaseShippingAmount = $expectedShippingAmount * $currencyMultiple;
     $expectedBaseShippingAmountInclTax = $expectedShippingAmountInclTax * $currencyMultiple;
     $grandTotalBefore = 100;
     $baseGrandTotalBefore = 200;
     $expectedGrandTotal = $grandTotalBefore + $expectedShippingAmount;
     $expectedBaseGrandTtoal = $baseGrandTotalBefore + $expectedBaseShippingAmount;
     $order = new \Magento\Framework\DataObject(['shipping_amount' => $orderShippingAmount, 'base_shipping_amount' => $baseOrderShippingAmount, 'shipping_refunded' => $orderShippingAmountRefunded, 'base_shipping_refunded' => $baseOrderShippingAmountRefunded, 'shipping_incl_tax' => $orderShippingInclTax, 'base_shipping_incl_tax' => $baseOrderShippingInclTax, 'shipping_tax_amount' => $shippingTaxAmount, 'shipping_tax_refunded' => $shippingTaxRefunded, 'base_shipping_tax_amount' => $baseShippingTaxAmount, 'base_shipping_tax_refunded' => $baseShippingTaxRefunded]);
     $this->creditmemoMock->expects($this->once())->method('getOrder')->willReturn($order);
     $this->creditmemoMock->expects($this->once())->method('hasBaseShippingAmount')->willReturn(true);
     $this->creditmemoMock->expects($this->once())->method('getBaseShippingAmount')->willReturn($desiredRefundAmount);
     $this->creditmemoMock->expects($this->once())->method('getGrandTotal')->willReturn($grandTotalBefore);
     $this->creditmemoMock->expects($this->once())->method('getBaseGrandTotal')->willReturn($baseGrandTotalBefore);
     //verify
     $this->creditmemoMock->expects($this->once())->method('setShippingAmount')->with($expectedShippingAmount)->willReturnSelf();
     $this->creditmemoMock->expects($this->once())->method('setBaseShippingAmount')->with($expectedBaseShippingAmount)->willReturnSelf();
     $this->creditmemoMock->expects($this->once())->method('setShippingInclTax')->with($expectedShippingAmountInclTax)->willReturnSelf();
     $this->creditmemoMock->expects($this->once())->method('setBaseShippingInclTax')->with($expectedBaseShippingAmountInclTax)->willReturnSelf();
     $this->creditmemoMock->expects($this->once())->method('setGrandTotal')->with($expectedGrandTotal)->willReturnSelf();
     $this->creditmemoMock->expects($this->once())->method('setBaseGrandTotal')->with($expectedBaseGrandTtoal)->willReturnSelf();
     $this->shippingCollector->collect($this->creditmemoMock);
 }
 /**
  * {@inheritdoc}
  */
 public function calculateTax(\Magento\Tax\Api\Data\QuoteDetailsInterface $quoteDetails, $storeId = null, $round = true)
 {
     if ($storeId === null) {
         $storeId = $this->storeManager->getStore()->getStoreId();
     }
     // initial TaxDetails data
     $taxDetailsData = [TaxDetailsInterface::KEY_SUBTOTAL => 0.0, TaxDetailsInterface::KEY_TAX_AMOUNT => 0.0, TaxDetailsInterface::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT => 0.0, TaxDetailsInterface::KEY_APPLIED_TAXES => [], TaxDetailsInterface::KEY_ITEMS => []];
     $items = $quoteDetails->getItems();
     if (empty($items)) {
         return $this->taxDetailsDataObjectFactory->create()->setSubtotal(0.0)->setTaxAmount(0.0)->setDiscountTaxCompensationAmount(0.0)->setAppliedTaxes([])->setItems([]);
     }
     $this->computeRelationships($items);
     $calculator = $this->calculatorFactory->create($this->config->getAlgorithm($storeId), $storeId, $quoteDetails->getBillingAddress(), $quoteDetails->getShippingAddress(), $this->taxClassManagement->getTaxClassId($quoteDetails->getCustomerTaxClassKey(), 'customer'), $quoteDetails->getCustomerId());
     $processedItems = [];
     /** @var QuoteDetailsItemInterface $item */
     foreach ($this->keyedItems as $item) {
         if (isset($this->parentToChildren[$item->getCode()])) {
             $processedChildren = [];
             foreach ($this->parentToChildren[$item->getCode()] as $child) {
                 $processedItem = $this->processItem($child, $calculator, $round);
                 $taxDetailsData = $this->aggregateItemData($taxDetailsData, $processedItem);
                 $processedItems[$processedItem->getCode()] = $processedItem;
                 $processedChildren[] = $processedItem;
             }
             $processedItem = $this->calculateParent($processedChildren, $item->getQuantity());
             $processedItem->setCode($item->getCode());
             $processedItem->setType($item->getType());
         } else {
             $processedItem = $this->processItem($item, $calculator, $round);
             $taxDetailsData = $this->aggregateItemData($taxDetailsData, $processedItem);
         }
         $processedItems[$processedItem->getCode()] = $processedItem;
     }
     $taxDetailsDataObject = $this->taxDetailsDataObjectFactory->create();
     $this->dataObjectHelper->populateWithArray($taxDetailsDataObject, $taxDetailsData, '\\Magento\\Tax\\Api\\Data\\TaxDetailsInterface');
     $taxDetailsDataObject->setItems($processedItems);
     return $taxDetailsDataObject;
 }
Example #21
0
 /**
  * @return $this
  */
 protected function _initGrandTotal()
 {
     $store = $this->getStore();
     $parent = $this->getParentBlock();
     $grandototal = $parent->getTotal('grand_total');
     if (!$grandototal || !(double) $this->_source->getGrandTotal()) {
         return $this;
     }
     if ($this->_config->displaySalesTaxWithGrandTotal($store)) {
         $grandtotal = $this->_source->getGrandTotal();
         $baseGrandtotal = $this->_source->getBaseGrandTotal();
         $grandtotalExcl = $grandtotal - $this->_source->getTaxAmount();
         $baseGrandtotalExcl = $baseGrandtotal - $this->_source->getBaseTaxAmount();
         $grandtotalExcl = max($grandtotalExcl, 0);
         $baseGrandtotalExcl = max($baseGrandtotalExcl, 0);
         $totalExcl = new \Magento\Framework\DataObject(['code' => 'grand_total', 'strong' => true, 'value' => $grandtotalExcl, 'base_value' => $baseGrandtotalExcl, 'label' => __('Grand Total (Excl.Tax)')]);
         $totalIncl = new \Magento\Framework\DataObject(['code' => 'grand_total_incl', 'strong' => true, 'value' => $grandtotal, 'base_value' => $baseGrandtotal, 'label' => __('Grand Total (Incl.Tax)')]);
         $parent->addTotal($totalExcl, 'grand_total');
         $this->_addTax('grand_total');
         $parent->addTotal($totalIncl, 'tax');
     }
     return $this;
 }
 /**
  * {@inheritdoc}
  */
 public function calculateTax(QuoteDetails $quoteDetails, $storeId = null)
 {
     if (is_null($storeId)) {
         $storeId = $this->storeManager->getStore()->getStoreId();
     }
     // initial TaxDetails data
     $taxDetailsData = [TaxDetails::KEY_SUBTOTAL => 0.0, TaxDetails::KEY_TAX_AMOUNT => 0.0, TaxDetails::KEY_DISCOUNT_TAX_COMPENSATION_AMOUNT => 0.0, TaxDetails::KEY_APPLIED_TAXES => [], TaxDetails::KEY_ITEMS => []];
     $items = $quoteDetails->getItems();
     if (empty($items)) {
         return $this->taxDetailsBuilder->populateWithArray($taxDetailsData)->create();
     }
     $this->computeRelationships($items);
     $calculator = $this->calculatorFactory->create($this->config->getAlgorithm($storeId), $storeId, $quoteDetails->getBillingAddress(), $quoteDetails->getShippingAddress(), $this->taxClassService->getTaxClassId($quoteDetails->getCustomerTaxClassKey(), 'customer'), $quoteDetails->getCustomerId());
     $processedItems = [];
     /** @var QuoteDetailsItem $item */
     foreach ($this->keyedItems as $item) {
         if (isset($this->parentToChildren[$item->getCode()])) {
             $processedChildren = [];
             foreach ($this->parentToChildren[$item->getCode()] as $child) {
                 $processedItem = $this->processItem($child, $calculator);
                 $taxDetailsData = $this->aggregateItemData($taxDetailsData, $processedItem);
                 $processedItems[$processedItem->getCode()] = $processedItem;
                 $processedChildren[] = $processedItem;
             }
             $processedItemBuilder = $this->calculateParent($processedChildren, $item->getQuantity());
             $processedItemBuilder->setCode($item->getCode());
             $processedItemBuilder->setType($item->getType());
             $processedItem = $processedItemBuilder->create();
         } else {
             $processedItem = $this->processItem($item, $calculator);
             $taxDetailsData = $this->aggregateItemData($taxDetailsData, $processedItem);
         }
         $processedItems[$processedItem->getCode()] = $processedItem;
     }
     return $this->taxDetailsBuilder->populateWithArray($taxDetailsData)->setItems($processedItems)->create();
 }
Example #23
0
 public function testGetDisplaySubtotalBoth()
 {
     $this->taxConfig->expects($this->once())->method('displayCartSubtotalBoth');
     $this->totalsObj->getDisplaySubtotalBoth();
 }
Example #24
0
 /**
  * Check if we need display grid totals include tax
  *
  * @return bool
  */
 public function displayTotalsIncludeTax()
 {
     $result = $this->_taxConfig->displayCartSubtotalInclTax($this->getStore()) || $this->_taxConfig->displayCartSubtotalBoth($this->getStore());
     return $result;
 }
Example #25
0
 /**
  * @return bool
  */
 public function displayBoth()
 {
     return $this->_taxConfig->displayCartSubtotalBoth($this->getStore());
 }
 /**
  * Calculate item price and row total including/excluding tax based on total price rounding level
  *
  * @param QuoteDetailsItem $item
  * @param \Magento\Framework\Object $taxRateRequest
  * @param int $storeId
  * @return TaxDetailsItem
  */
 protected function totalBaseCalculation(QuoteDetailsItem $item, \Magento\Framework\Object $taxRateRequest, $storeId)
 {
     /** @var  \Magento\Tax\Service\V1\Data\TaxDetails\AppliedTax[] $appliedTaxes */
     $appliedTaxes = [];
     $appliedTaxBuilder = $this->taxDetailsItemBuilder->getAppliedTaxBuilder();
     $appliedTaxRateBuilder = $appliedTaxBuilder->getAppliedTaxRateBuilder();
     $taxRateRequest->setProductClassId($item->getTaxClassId());
     $appliedRates = $this->calculator->getAppliedRates($taxRateRequest);
     $rate = $this->calculator->getRate($taxRateRequest);
     $quantity = $this->getTotalQuantity($item);
     $price = $priceInclTax = $this->calculator->round($item->getUnitPrice());
     $rowTotal = $rowTotalInclTax = $taxableAmount = $this->calcRowTotal($item);
     $discountAmount = $item->getDiscountAmount();
     $applyTaxAfterDiscount = $this->config->applyTaxAfterDiscount($storeId);
     $discountTaxCompensationAmount = 0;
     $isTotalBasedCalculation = $this->config->getAlgorithm($storeId) == Calculation::CALC_TOTAL_BASE;
     if ($item->getTaxIncluded()) {
         if ($taxRateRequest->getSameRateAsStore()) {
             $rowTaxExact = $this->calculator->calcTaxAmount($rowTotalInclTax, $rate, true, false);
             if ($isTotalBasedCalculation) {
                 $rowTax = $this->deltaRound($rowTaxExact, $rate, true);
             } else {
                 $rowTax = $this->calculator->round($rowTaxExact);
             }
             $rowTotal = $rowTotalInclTax - $rowTax;
             $price = $this->calculator->round($rowTotal / $quantity);
         } else {
             $storeRate = $this->calculator->getStoreRate($taxRateRequest, $storeId);
             $priceInclTax = $this->calculatePriceInclTax($price, $storeRate, $rate);
             $rowTotalInclTax = $priceInclTax * $quantity;
             $taxableAmount = $rowTotalInclTax;
             if ($isTotalBasedCalculation) {
                 $rowTax = $this->deltaRound($this->calculator->calcTaxAmount($rowTotalInclTax, $rate, true, false), $rate, true);
             } else {
                 $rowTax = $this->calculator->calcTaxAmount($rowTotalInclTax, $rate, true, true);
             }
             $rowTotal = $rowTotalInclTax - $rowTax;
             $price = $this->calculator->round($rowTotal / $quantity);
         }
         //Handle discount
         if ($discountAmount && $applyTaxAfterDiscount) {
             //TODO: handle originalDiscountAmount
             $taxableAmount = max($taxableAmount - $discountAmount, 0);
             $rowTaxAfterDiscount = $this->calculator->calcTaxAmount($taxableAmount, $rate, true, false);
             if ($isTotalBasedCalculation) {
                 //Round the row tax using a different type so that we don't pollute the rounding deltas
                 $rowTaxAfterDiscount = $this->deltaRound($rowTaxAfterDiscount, $rate, true, self::KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING);
             } else {
                 $rowTaxAfterDiscount = $this->calculator->round($rowTaxAfterDiscount);
             }
             // Set discount tax compensation
             $discountTaxCompensationAmount = $rowTax - $rowTaxAfterDiscount;
             $rowTax = $rowTaxAfterDiscount;
         }
         //save applied taxes
         $appliedTaxes = $this->getAppliedTaxes($appliedTaxBuilder, $rowTax, $rate, $appliedRates);
     } else {
         //catalog price does not include tax
         $appliedRates = $this->calculator->getAppliedRates($taxRateRequest);
         $rowTaxes = [];
         $rowTaxesBeforeDiscount = [];
         //Apply each tax rate separately
         foreach ($appliedRates as $appliedRate) {
             $taxId = $appliedRate['id'];
             $taxRate = $appliedRate['percent'];
             if ($isTotalBasedCalculation) {
                 $rowTaxPerRate = $this->deltaRound($this->calculator->calcTaxAmount($rowTotal, $taxRate, false, false), $taxId, false);
             } else {
                 $rowTaxPerRate = $this->calculator->calcTaxAmount($rowTotal, $taxRate, false, true);
             }
             $rowTaxAfterDiscount = $rowTaxPerRate;
             //Handle discount
             if ($discountAmount && $applyTaxAfterDiscount) {
                 //TODO: handle originalDiscountAmount
                 $rowTaxAfterDiscount = $this->calculator->calcTaxAmount(max($rowTotal - $discountAmount, 0), $taxRate, false, false);
                 if ($isTotalBasedCalculation) {
                     //Round the row tax using a different type so that we don't pollute the rounding deltas
                     $rowTaxAfterDiscount = $this->deltaRound($rowTaxAfterDiscount, $taxRate, false, self::KEY_TAX_AFTER_DISCOUNT_DELTA_ROUNDING);
                 } else {
                     $rowTaxAfterDiscount = $this->calculator->round($rowTaxAfterDiscount);
                 }
             }
             $appliedTaxes[$appliedRate['id']] = $this->getAppliedTax($appliedTaxBuilder, $rowTaxAfterDiscount, $appliedRate);
             $rowTaxes[] = $rowTaxAfterDiscount;
             $rowTaxesBeforeDiscount[] = $rowTaxPerRate;
         }
         $rowTax = array_sum($rowTaxes);
         $rowTaxBeforeDiscount = array_sum($rowTaxesBeforeDiscount);
         $rowTotalInclTax = $rowTotal + $rowTaxBeforeDiscount;
         $priceInclTax = $this->calculator->round($rowTotalInclTax / $quantity);
     }
     $this->taxDetailsItemBuilder->setCode($item->getCode());
     $this->taxDetailsItemBuilder->setRowTax($rowTax);
     $this->taxDetailsItemBuilder->setPrice($price);
     $this->taxDetailsItemBuilder->setPriceInclTax($priceInclTax);
     $this->taxDetailsItemBuilder->setRowTotal($rowTotal);
     $this->taxDetailsItemBuilder->setRowTotalInclTax($rowTotalInclTax);
     $this->taxDetailsItemBuilder->setCode($item->getCode());
     $this->taxDetailsItemBuilder->setType($item->getType());
     $this->taxDetailsItemBuilder->setTaxPercent($rate);
     $this->taxDetailsItemBuilder->setDiscountTaxCompensationAmount($discountTaxCompensationAmount);
     $this->taxDetailsItemBuilder->setAppliedTaxes($appliedTaxes);
     return $this->taxDetailsItemBuilder->create();
 }
 /**
  * Get totals config
  *
  * @return array
  */
 protected function getTotalsConfig()
 {
     return ['display_subtotal_incl_tax' => (int) $this->taxConfig->displayCartSubtotalInclTax(), 'display_cart_subtotal_excl_tax' => (int) $this->taxConfig->displayCartSubtotalExclTax()];
 }
 /**
  * Display tax in grand total section or not
  *
  * @return bool
  */
 public function isTaxDisplayedInGrandTotal()
 {
     return $this->taxConfig->displayCartTaxWithGrandTotal();
 }
Example #29
0
 /**
  * Return whether cross border trade is enabled or not
  *
  * @param   null|int|string|Store $store
  * @return  bool
  */
 public function isCrossBorderTradeEnabled($store = null)
 {
     return (bool) $this->_config->crossBorderTradeEnabled($store);
 }
Example #30
0
 /**
  * Check if we need display shipping include tax
  *
  * @return bool
  */
 public function displayIncludeTax()
 {
     return $this->_taxConfig->displayCartShippingInclTax($this->getStore());
 }