diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php index 630e51d3c244aaa1e63550285d7d91cc62cd2d3d..6e1154ff4c4d58ad95d8be6eadde211be84e165c 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php @@ -569,6 +569,7 @@ class BundlePanel extends AbstractModifier 'arguments' => [ 'data' => [ 'config' => [ + 'component' => 'Magento_Bundle/js/components/bundle-option-qty', 'formElement' => Form\Element\Input::NAME, 'componentType' => Form\Field::NAME, 'dataType' => Form\Element\DataType\Number::NAME, @@ -577,8 +578,12 @@ class BundlePanel extends AbstractModifier 'value' => '1', 'sortOrder' => 100, 'validation' => [ + 'required-entry' => true, 'validate-number' => true, ], + 'imports' => [ + 'isInteger' => '${ $.provider }:${ $.parentScope }.selection_qty_is_integer' + ], ], ], ], diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php index 008bb7b6a608672d7ff2d9a90405b44c8692b3c3..8fcf53f8950074ca94352639d5bf161898c8a1a5 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php @@ -88,6 +88,8 @@ class Composite extends AbstractModifier /** * {@inheritdoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) */ public function modifyData(array $data) { @@ -103,6 +105,12 @@ class Composite extends AbstractModifier /** @var \Magento\Bundle\Api\Data\LinkInterface $productLink */ foreach ($option->getProductLinks() as $productLink) { $linkedProduct = $this->productRepository->get($productLink->getSku()); + $integerQty = 1; + if ($linkedProduct->getExtensionAttributes()->getStockItem()) { + if ($linkedProduct->getExtensionAttributes()->getStockItem()->getIsQtyDecimal()) { + $integerQty = 0; + } + } $selections[] = [ 'selection_id' => $productLink->getId(), 'option_id' => $productLink->getOptionId(), @@ -112,8 +120,9 @@ class Composite extends AbstractModifier 'is_default' => ($productLink->getIsDefault()) ? '1' : '0', 'selection_price_value' => $productLink->getPrice(), 'selection_price_type' => $productLink->getPriceType(), - 'selection_qty' => $productLink->getQty(), + 'selection_qty' => (bool)$integerQty ? (int)$productLink->getQty() : $productLink->getQty(), 'selection_can_change_qty' => $productLink->getCanChangeQuantity(), + 'selection_qty_is_integer' => (bool)$integerQty, 'position' => $productLink->getPosition(), ]; } diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/product/edit/bundle/option/selection.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/product/edit/bundle/option/selection.phtml index 11d43466c394218199d6dbab618c9b72a078c6ec..5dbeebea8f3e9679ea2f6c9ee5889c9f6d65108b 100644 --- a/app/code/Magento/Bundle/view/adminhtml/templates/product/edit/bundle/option/selection.phtml +++ b/app/code/Magento/Bundle/view/adminhtml/templates/product/edit/bundle/option/selection.phtml @@ -164,7 +164,7 @@ Bundle.Selection.prototype = { if (data.can_read_price != undefined && !data.can_read_price) { data.selection_price_value = ''; } else { - data.selection_price_value = Number(data.selection_price_value).toFixed(2); + data.selection_price_value = Number(Math.round(data.selection_price_value + "e+2") + "e-2").toFixed(2); } data.index = this.itemsCount++; diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js new file mode 100644 index 0000000000000000000000000000000000000000..a52d4e8a4683bc1a6c2745a528fe1a12b7f092cb --- /dev/null +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js @@ -0,0 +1,26 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'Magento_Ui/js/form/element/abstract' +], function (Abstract) { + 'use strict'; + + return Abstract.extend({ + defaults: { + valueUpdate: 'input', + isInteger: true + }, + + /** + * update event + */ + onUpdate: function () { + this.validation['validate-number'] = true; + this.validation['validate-digits'] = this.isInteger; + this.validate(); + } + }); +}); diff --git a/app/code/Magento/Catalog/view/base/web/js/price-utils.js b/app/code/Magento/Catalog/view/base/web/js/price-utils.js index f97e01f14117009660556a343d0504436c668f6d..0291d82845368d0282f0f9b5c8879a0d2383c46d 100644 --- a/app/code/Magento/Catalog/view/base/web/js/price-utils.js +++ b/app/code/Magento/Catalog/view/base/web/js/price-utils.js @@ -43,7 +43,7 @@ define([ pattern = format.pattern || '%s', s = '', i, pad, - j, re, r; + j, re, r, am; if (isShowSign === undefined || isShowSign === true) { s = amount < 0 ? '-' : (isShowSign ? '+' : ''); @@ -52,7 +52,9 @@ define([ } pattern = pattern.indexOf('{sign}') < 0 ? s + pattern : pattern.replace('{sign}', s); - i = parseInt(amount = Math.abs(+amount || 0).toFixed(precision), 10) + ''; + // we're avoiding the usage of to fixed, and using round instead with the e representation to address + // numbers like 1.005 = 1.01. Using ToFixed to only provide trailig zeroes in case we have a whole number + i = parseInt(amount = Number(Math.round(Math.abs(+amount || 0) + 'e+' + precision) + ('e-' + precision)) , 10) + ''; pad = (i.length < integerRequired) ? (integerRequired - i.length) : 0; i = stringPad('0', pad) + i; @@ -63,9 +65,12 @@ define([ // replace(/-/, 0) is only for fixing Safari bug which appears // when Math.abs(0).toFixed() executed on '0' number. // Result is '0.-0' :( + + + am = Number(Math.round(Math.abs(amount - i) + 'e+' + precision) + ('e-' + precision)); r = (j ? i.substr(0, j) + groupSymbol : '') + i.substr(j).replace(re, '$1' + groupSymbol) + - (precision ? decimalSymbol + Math.abs(amount - i).toFixed(precision).replace(/-/, 0).slice(2) : ''); + (precision ? decimalSymbol + am.toFixed(2).replace(/-/, 0).slice(2) : ''); return pattern.replace('%s', r).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); } diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js index e2a89cba9519f31f7d4e78505d363e6a9d58b261..b138e1243e89412ffa8ac426bd732307bda6483f 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/configurable.js @@ -214,7 +214,7 @@ Product.Config.prototype = { } } - var roundedPrice = (Math.round(price*100)/100).toString(); + var roundedPrice = Number(Math.round(price + "e+2") + "e-2").toString(); if (this.prices && this.prices[roundedPrice]) { str+= this.prices[roundedPrice]; diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js index f05e524439af5a9b3917807eaabd43a11524918a..878b0459fb0e96638fb7103b862442ec009b74e6 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/variations/variations.js @@ -124,7 +124,7 @@ define([ }, name: product.name || product.sku, options: options, - price: parseFloat(product.price.replace(/[^\d.]+/g, '')).toFixed(4), + price: parseFloat(Math.round(product.price.replace(/[^\d.]+/g, '') + "e+4") + "e-4").toFixed(4), productId: productId, productUrl: this.buildProductUrl(productId), quantity: product.quantity || null, diff --git a/app/code/Magento/Quote/etc/fieldset.xml b/app/code/Magento/Quote/etc/fieldset.xml index acb860fa1733d1be7c919a602fe7c4e10388f10c..36f0b2d1331052660a6a9dac02e23fefc755fb8f 100644 --- a/app/code/Magento/Quote/etc/fieldset.xml +++ b/app/code/Magento/Quote/etc/fieldset.xml @@ -247,6 +247,9 @@ <field name="row_total"> <aspect name="to_order_item" /> </field> + <field name="base_price"> + <aspect name="to_order_item" /> + </field> <field name="base_original_price"> <aspect name="to_order_item" /> </field> diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php index a5cbd3431b33765263d3fd6e5b9bee27ea9b42ea..0a2596029de8a2f480b9ee6a37e12097cb8188dd 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Shipping.php @@ -17,6 +17,13 @@ class Shipping extends AbstractTotal */ protected $priceCurrency; + /** + * Tax config + * + * @var \Magento\Tax\Model\Config + */ + private $taxConfig; + /** * @param PriceCurrencyInterface $priceCurrency * @param array $data @@ -37,62 +44,64 @@ class Shipping extends AbstractTotal public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) { $order = $creditmemo->getOrder(); - $allowedAmount = $order->getShippingAmount() - $order->getShippingRefunded(); - $baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded(); + // amounts without tax $orderShippingAmount = $order->getShippingAmount(); $orderBaseShippingAmount = $order->getBaseShippingAmount(); + $allowedAmount = $orderShippingAmount - $order->getShippingRefunded(); + $baseAllowedAmount = $orderBaseShippingAmount - $order->getBaseShippingRefunded(); + + // amounts including tax $orderShippingInclTax = $order->getShippingInclTax(); $orderBaseShippingInclTax = $order->getBaseShippingInclTax(); + $allowedTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded(); + $baseAllowedTaxAmount = $order->getBaseShippingTaxAmount() - $order->getBaseShippingTaxRefunded(); + $allowedAmountInclTax = $allowedAmount + $allowedTaxAmount; + $baseAllowedAmountInclTax = $baseAllowedAmount + $baseAllowedTaxAmount; + // for the credit memo $shippingAmount = $baseShippingAmount = $shippingInclTax = $baseShippingInclTax = 0; - /** - * Check if shipping amount was specified (from invoice or another source). - * Using has magic method to allow setting 0 as shipping amount. - */ + // Check if the desired shipping amount to refund was specified (from invoice or another source). if ($creditmemo->hasBaseShippingAmount()) { - $baseShippingAmount = $this->priceCurrency->round($creditmemo->getBaseShippingAmount()); - /* - * Rounded allowed shipping refund amount is the highest acceptable shipping refund amount. - * Shipping refund amount shouldn't cause errors, if it doesn't exceed that limit. - * Note: ($x < $y + 0.0001) means ($x <= $y) for floats - */ - if ($baseShippingAmount < $this->priceCurrency->round($baseAllowedAmount) + 0.0001) { + // For the conditional logic, we will either use amounts that always include tax -OR- never include tax. + // The logic uses the 'base' currency to be consistent with what the user (admin) provided as input. + $useAmountsWithTax = $this->isSuppliedShippingAmountInclTax($order); + + // Since the user (admin) supplied 'desiredAmount' it already has tax -OR- does not include tax + $desiredAmount = $this->priceCurrency->round($creditmemo->getBaseShippingAmount()); + $maxAllowedAmount = ($useAmountsWithTax ? $baseAllowedAmountInclTax : $baseAllowedAmount); + $originalTotalAmount = ($useAmountsWithTax ? $orderBaseShippingInclTax : $orderBaseShippingAmount); + + // Note: ($x < $y + 0.0001) means ($x <= $y) for floats + if ($desiredAmount < $this->priceCurrency->round($maxAllowedAmount) + 0.0001) { + // since the admin is returning less than the allowed amount, compute the ratio being returned $ratio = 0; - if ($orderBaseShippingAmount > 0) { - $ratio = $baseShippingAmount / $orderBaseShippingAmount; + if ($originalTotalAmount > 0) { + $ratio = $desiredAmount / $originalTotalAmount; } - /* - * Shipping refund amount should be equated to allowed refund amount, - * if it exceeds that limit. - * Note: ($x > $y - 0.0001) means ($x >= $y) for floats - */ - if ($baseShippingAmount > $baseAllowedAmount - 0.0001) { + // capture amounts without tax + // Note: ($x > $y - 0.0001) means ($x >= $y) for floats + if ($desiredAmount > $maxAllowedAmount - 0.0001) { $shippingAmount = $allowedAmount; $baseShippingAmount = $baseAllowedAmount; } else { $shippingAmount = $this->priceCurrency->round($orderShippingAmount * $ratio); + $baseShippingAmount = $this->priceCurrency->round($orderBaseShippingAmount * $ratio); } $shippingInclTax = $this->priceCurrency->round($orderShippingInclTax * $ratio); $baseShippingInclTax = $this->priceCurrency->round($orderBaseShippingInclTax * $ratio); } else { - $baseAllowedAmount = $order->getBaseCurrency()->format($baseAllowedAmount, null, false); + $maxAllowedAmount = $order->getBaseCurrency()->format($maxAllowedAmount, null, false); throw new \Magento\Framework\Exception\LocalizedException( - __('Maximum shipping amount allowed to refund is: %1', $baseAllowedAmount) + __('Maximum shipping amount allowed to refund is: %1', $maxAllowedAmount) ); } } else { $shippingAmount = $allowedAmount; $baseShippingAmount = $baseAllowedAmount; - - $allowedTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded(); - $baseAllowedTaxAmount = $order->getBaseShippingTaxAmount() - $order->getBaseShippingTaxRefunded(); - - $shippingInclTax = $this->priceCurrency->round($allowedAmount + $allowedTaxAmount); - $baseShippingInclTax = $this->priceCurrency->round( - $baseAllowedAmount + $baseAllowedTaxAmount - ); + $shippingInclTax = $this->priceCurrency->round($allowedAmountInclTax); + $baseShippingInclTax = $this->priceCurrency->round($baseAllowedAmountInclTax); } $creditmemo->setShippingAmount($shippingAmount); @@ -104,4 +113,32 @@ class Shipping extends AbstractTotal $creditmemo->setBaseGrandTotal($creditmemo->getBaseGrandTotal() + $baseShippingAmount); return $this; } + + /** + * Returns whether the user specified a shipping amount that already includes tax + * + * @param \Magento\Sales\Model\Order $order + * @return bool + */ + private function isSuppliedShippingAmountInclTax($order) + { + // returns true if we are only displaying shipping including tax, otherwise returns false + return $this->getTaxConfig()->displaySalesShippingInclTax($order->getStoreId()); + } + + /** + * Get the Tax Config. + * In a future release, will become a constructor parameter. + * + * @return \Magento\Tax\Model\Config + * + * @deprecated + */ + private function getTaxConfig() + { + if ($this->taxConfig === null) { + $this->taxConfig = \Magento\Framework\App\ObjectManager::getInstance()->get('Magento\Tax\Model\Config'); + } + return $this->taxConfig; + } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/ShippingTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/ShippingTest.php index 54391701b8c38874d392615d246463877a0b3b37..52624f64592926cadf61ae75ed7d05a6c18149e3 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/ShippingTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/ShippingTest.php @@ -15,6 +15,11 @@ class ShippingTest extends \PHPUnit_Framework_TestCase */ protected $creditmemoMock; + /** + * @var \Magento\Tax\Model\Config|\PHPUnit_Framework_MockObject_MockObject + */ + protected $taxConfig; + /** * @var \Magento\Sales\Model\Order\Creditmemo\Total\Shipping */ @@ -51,16 +56,24 @@ class ShippingTest extends \PHPUnit_Framework_TestCase } ); + $this->taxConfig = $this->getMock('Magento\Tax\Model\Config', [], [], '', false); + $this->shippingCollector = $objectManager->getObject( 'Magento\Sales\Model\Order\Creditmemo\Total\Shipping', [ 'priceCurrency' => $priceCurrencyMock, ] ); + + // needed until 'taxConfig' becomes part of the constructor for shippingCollector + $reflection = new \ReflectionClass(get_class($this->shippingCollector)); + $reflectionProperty = $reflection->getProperty('taxConfig'); + $reflectionProperty->setAccessible(true); + $reflectionProperty->setValue($this->shippingCollector, $this->taxConfig); } /** - * Test the case where shipping amount specified is greater than shipping amount allowed + * situation: The admin user specified a desired shipping refund that is greater than the amount allowed * * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage Maximum shipping amount allowed to refund is: 5 @@ -70,7 +83,10 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $orderShippingAmount = 10; $orderShippingRefunded = 5; $allowedShippingAmount = $orderShippingAmount - $orderShippingRefunded; - $creditmemoShippingAmount = 6; + $desiredRefundAmount = $allowedShippingAmount + 1; // force amount to be larger than what is allowed + + $this->taxConfig->expects($this->any())->method('displaySalesShippingInclTax')->willReturn(false); + $currencyMock = $this->getMockBuilder('Magento\Directory\Model\Currency') ->disableOriginalConstructor() ->getMock(); @@ -78,6 +94,7 @@ class ShippingTest extends \PHPUnit_Framework_TestCase ->method('format') ->with($allowedShippingAmount, null, false) ->willReturn($allowedShippingAmount); + $order = new \Magento\Framework\DataObject( [ 'base_shipping_amount' => $orderShippingAmount, @@ -89,18 +106,22 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $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($creditmemoShippingAmount); - + ->willReturn($desiredRefundAmount); + //expect to have an exception thrown $this->shippingCollector->collect($this->creditmemoMock); } + /** + * situation: The admin user did *not* specify any desired refund amount + * + * @throws \Magento\Framework\Exception\LocalizedException + */ public function testCollectNoSpecifiedShippingAmount() { $orderShippingAmount = 10; @@ -122,6 +143,8 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $expectedGrandTotal = $grandTotalBefore + $allowedShippingAmount; $expectedBaseGrandTtoal = $baseGrandTotalBefore + $baseAllowedShippingAmount; + $this->taxConfig->expects($this->any())->method('displaySalesShippingInclTax')->willReturn(false); + $order = new \Magento\Framework\DataObject( [ 'shipping_amount' => $orderShippingAmount, @@ -140,11 +163,9 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $this->creditmemoMock->expects($this->once()) ->method('getOrder') ->willReturn($order); - $this->creditmemoMock->expects($this->once()) ->method('hasBaseShippingAmount') ->willReturn(false); - $this->creditmemoMock->expects($this->once()) ->method('getGrandTotal') ->willReturn($grandTotalBefore); @@ -196,8 +217,8 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $orderShippingInclTax = $orderShippingAmount + $shippingTaxAmount; $baseOrderShippingInclTax = $baseOrderShippingAmount + $baseShippingTaxAmount; - //refund half - $creditmemoBaseShippingAmount = $ratio * $baseOrderShippingAmount; + //determine expected partial refund amounts + $desiredRefundAmount = $baseOrderShippingAmount * $ratio; $expectedShippingAmount = $orderShippingAmount * $ratio; $expectedShippingAmountInclTax = $orderShippingInclTax * $ratio; @@ -209,6 +230,8 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $expectedGrandTotal = $grandTotalBefore + $expectedShippingAmount; $expectedBaseGrandTtoal = $baseGrandTotalBefore + $expectedBaseShippingAmount; + $this->taxConfig->expects($this->any())->method('displaySalesShippingInclTax')->willReturn(false); + $order = new \Magento\Framework\DataObject( [ 'shipping_amount' => $orderShippingAmount, @@ -223,14 +246,12 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $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($creditmemoBaseShippingAmount); - + ->willReturn($desiredRefundAmount); $this->creditmemoMock->expects($this->once()) ->method('getGrandTotal') ->willReturn($grandTotalBefore); @@ -267,6 +288,9 @@ class ShippingTest extends \PHPUnit_Framework_TestCase $this->shippingCollector->collect($this->creditmemoMock); } + /** + * @return array + */ public function collectWithSpecifiedShippingAmountDataProvider() { return [ @@ -274,4 +298,102 @@ class ShippingTest extends \PHPUnit_Framework_TestCase 'quarter' => [0.25], ]; } + + /** + * 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); + } } diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js index bec36e6206eddcf7c1344d2626f0e5ca1e8c2a5e..6e5eca5d94be422e1efad40d7e69a59042e0a446 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js @@ -539,7 +539,7 @@ define([ if (this._isSummarizePrice()) { productPrice += this.productPriceBase[productId]; } - productPrice = parseFloat(productPrice); + productPrice = parseFloat(Math.round(productPrice + "e+2") + "e-2"); priceColl.innerHTML = this.currencySymbol + productPrice.toFixed(2); // and set checkbox checked grid.setCheckboxChecked(checkbox, true); diff --git a/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js b/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js index 645e43bfb869ee4c137ea15578f813beaabf72d9..1e6c9a4465049127168a4ed5b7ffb348c534ba4f 100644 --- a/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js +++ b/app/code/Magento/Shipping/view/adminhtml/web/order/packaging.js @@ -728,7 +728,7 @@ Packaging.prototype = { item.remove(); } else if (qtyValue > packedQty) { /* fix float number precision */ - qty.value = Number((qtyValue - packedQty).toFixed(4)); + qty.value = Number(Number(Math.round((qtyValue - packedQty) + "e+4") + "e-4").toFixed(4)); } } } @@ -786,8 +786,8 @@ Packaging.prototype = { containerCustomsValue.value = parseFloat(containerCustomsValue.value) + itemCustomsValue * qtyValue; this.packages[packageId]['items'][itemId]['customs_value'] = itemCustomsValue; }.bind(this)); - containerWeight.value = parseFloat(parseFloat(containerWeight.value).toFixed(4)); - containerCustomsValue.value = parseFloat(containerCustomsValue.value).toFixed(2); + containerWeight.value = parseFloat(parseFloat(Math.round(containerWeight.value + "e+4") + "e-4").toFixed(4)); + containerCustomsValue.value = parseFloat(Math.round(containerCustomsValue.value + "e+2") + "e-2").toFixed(2); if (containerCustomsValue.value == 0) { containerCustomsValue.value = ''; } diff --git a/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php b/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php index b49e43108e40bd270bb01b4e9b508d0e7406a7d3..e8700e714951c823abbc23c309299d11235a8b15 100644 --- a/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php +++ b/app/code/Magento/Tax/Model/Sales/Order/TaxManagement.php @@ -66,18 +66,27 @@ class TaxManagement implements \Magento\Tax\Api\OrderTaxManagementInterface * * @param TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory * @param array $itemAppliedTax + * @param AppliedTax $existingAppliedTax * @return AppliedTax */ protected function convertToAppliedTaxDataObject( TaxDetailsDataObjectFactory $appliedTaxDataObjectFactory, - $itemAppliedTax + $itemAppliedTax, + AppliedTax $existingAppliedTax = null ) { + // if there is an existingAppliedTax, include its amount and baseAmount + $amount = $baseAmount = 0; + if ($existingAppliedTax !== null) { + $amount = $existingAppliedTax->getAmount(); + $baseAmount = $existingAppliedTax->getBaseAmount(); + } + return $appliedTaxDataObjectFactory->create() ->setCode($itemAppliedTax['code']) ->setTitle($itemAppliedTax['title']) ->setPercent($itemAppliedTax['tax_percent']) - ->setAmount($itemAppliedTax['real_amount']) - ->setBaseAmount($itemAppliedTax['real_base_amount']); + ->setAmount($itemAppliedTax['real_amount'] + $amount) + ->setBaseAmount($itemAppliedTax['real_base_amount'] + $baseAmount); } /** @@ -141,46 +150,39 @@ class TaxManagement implements \Magento\Tax\Api\OrderTaxManagementInterface $orderItemAppliedTaxes = $this->orderItemTaxFactory->create()->getTaxItemsByOrderId($orderId); $itemsData = []; foreach ($orderItemAppliedTaxes as $itemAppliedTax) { + $key = $itemId = $associatedItemId = null; + //group applied taxes by item if (isset($itemAppliedTax['item_id'])) { //The taxable is a product + //Note: the associatedItemId is null $itemId = $itemAppliedTax['item_id']; - if (!isset($itemsData[$itemId])) { - $itemsData[$itemId] = [ - Item::KEY_ITEM_ID => $itemAppliedTax['item_id'], - Item::KEY_TYPE => $itemAppliedTax['taxable_item_type'], - Item::KEY_ASSOCIATED_ITEM_ID => null, - ]; - } - $itemsData[$itemId]['applied_taxes'][$itemAppliedTax['code']] = - $this->convertToAppliedTaxDataObject($this->appliedTaxDataObjectFactory, $itemAppliedTax); + $key = $itemId; } elseif (isset($itemAppliedTax['associated_item_id'])) { - //The taxable is associated with a product, e.g., weee, gift wrapping etc. - $itemId = $itemAppliedTax['associated_item_id']; - $key = $itemAppliedTax['taxable_item_type'] . $itemId; - if (!isset($itemsData[$key])) { - $itemsData[$key] = [ - Item::KEY_ITEM_ID => null, - Item::KEY_TYPE => $itemAppliedTax['taxable_item_type'], - Item::KEY_ASSOCIATED_ITEM_ID => $itemId, - ]; - } - $itemsData[$key]['applied_taxes'][$itemAppliedTax['code']] = - $this->convertToAppliedTaxDataObject($this->appliedTaxDataObjectFactory, $itemAppliedTax); + //The taxable is associated with a product, e.g., weee, gift wrapping, etc. + //Note: the itemId is null + $associatedItemId = $itemAppliedTax['associated_item_id']; + $key = $itemAppliedTax['taxable_item_type'] . $associatedItemId; } else { //The taxable is not associated with a product, e.g., shipping - //Use item type as key + //Use item type as key. Both the itemId and associatedItemId are null $key = $itemAppliedTax['taxable_item_type']; - if (!isset($itemsData[$key])) { - $itemsData[$key] = [ - Item::KEY_TYPE => $itemAppliedTax['taxable_item_type'], - Item::KEY_ITEM_ID => null, - Item::KEY_ASSOCIATED_ITEM_ID => null, - ]; - } - $itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']] = - $this->convertToAppliedTaxDataObject($this->appliedTaxDataObjectFactory, $itemAppliedTax); } + + // create the itemsData entry + if (!isset($itemsData[$key])) { + $itemsData[$key] = [ + Item::KEY_TYPE => $itemAppliedTax['taxable_item_type'], + Item::KEY_ITEM_ID => $itemId, // might be null + Item::KEY_ASSOCIATED_ITEM_ID => $associatedItemId, // might be null + ]; + } + $current = null; + if (isset($itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']])) { + $current = $itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']]; + } + $itemsData[$key][Item::KEY_APPLIED_TAXES][$itemAppliedTax['code']] = + $this->convertToAppliedTaxDataObject($this->appliedTaxDataObjectFactory, $itemAppliedTax, $current); } $items = []; diff --git a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php index 1870806dd4262d5359598a0049e57535989a5aac..bc241592f9184625ca86b1d21b03a17809f43c9b 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Quote/GrandTotalDetailsPluginTest.php @@ -63,10 +63,12 @@ class GrandTotalDetailsPluginTest extends \PHPUnit_Framework_TestCase $this->detailsFactoryMock = $this->getMockBuilder('\Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory') ->disableOriginalConstructor() + ->setMethods(['create']) ->getMock(); $this->ratesFactoryMock = $this->getMockBuilder('\Magento\Tax\Api\Data\GrandTotalRatesInterfaceFactory') ->disableOriginalConstructor() + ->setMethods(['create']) ->getMock(); $this->taxConfigMock = $this->getMockBuilder('\Magento\Tax\Model\Config') @@ -154,7 +156,6 @@ class GrandTotalDetailsPluginTest extends \PHPUnit_Framework_TestCase ]; $taxAmount = 10; - $taxRateMock = $this->setupTaxRateFactoryMock($taxRate); $taxDetailsMock = $this->setupTaxDetails( @@ -190,7 +191,6 @@ class GrandTotalDetailsPluginTest extends \PHPUnit_Framework_TestCase ->with([$taxDetailsMock]) ->willReturnSelf(); - $taxSegmentMock = $this->getMockBuilder('\Magento\Quote\Model\Cart\TotalSegment') ->disableOriginalConstructor() ->getMock(); diff --git a/app/code/Magento/Tax/Test/Unit/Model/Sales/Order/TaxManagementTest.php b/app/code/Magento/Tax/Test/Unit/Model/Sales/Order/TaxManagementTest.php index cd7198e336ddc22d5b3e9dd2bd2ce9a184f698f5..4c78af20608ac9e6cc14933eb884d2521be0924f 100644 --- a/app/code/Magento/Tax/Test/Unit/Model/Sales/Order/TaxManagementTest.php +++ b/app/code/Magento/Tax/Test/Unit/Model/Sales/Order/TaxManagementTest.php @@ -26,36 +26,6 @@ class TaxManagementTest extends \PHPUnit_Framework_TestCase */ private $taxItemResourceMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $taxItemFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $orderFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $appliedTaxDataObjectFactoryMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $itemDataObjectFactoryMock; - - /** - * @var \Magento\Tax\Api\Data\OrderTaxDetailsItemInterface - */ - protected $itemDataObject; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $orderTaxDetailsDataObjectFactoryMock; - /** * @var \Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface */ @@ -68,85 +38,85 @@ class TaxManagementTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->orderMock = $this->getMock('Magento\Sales\Model\Order', [], [], '', false); - $this->orderFactoryMock = $this->getMock('Magento\Sales\Model\OrderFactory', ['create'], [], '', false); - $this->taxItemResourceMock = $this->getMock( - 'Magento\Sales\Model\ResourceModel\Order\Tax\Item', - [], - [], - '', - false - ); - $this->taxItemFactoryMock = $this->getMock( - 'Magento\Sales\Model\ResourceModel\Order\Tax\ItemFactory', - ['create'], - [], - '', - false - ); + $this->orderMock = $this->getMock('Magento\Sales\Model\Order', ['load'], [], '', false); - $objectManager = new ObjectManager($this); $methods = ['create']; + $orderFactoryMock = $this->getMock('Magento\Sales\Model\OrderFactory', $methods, [], '', false); + $orderFactoryMock->expects($this->atLeastOnce()) + ->method('create') + ->will($this->returnValue($this->orderMock)); + + $className = 'Magento\Sales\Model\ResourceModel\Order\Tax\Item'; + $this->taxItemResourceMock = $this->getMock($className, ['getTaxItemsByOrderId'], [], '', false); + + $className = 'Magento\Sales\Model\ResourceModel\Order\Tax\ItemFactory'; + $taxItemFactoryMock = $this->getMock($className, $methods, [], '', false); + $taxItemFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->taxItemResourceMock); + + $objectManager = new ObjectManager($this); $this->appliedTaxDataObject = $objectManager->getObject('Magento\Tax\Model\Sales\Order\Tax'); - $this->appliedTaxDataObjectFactoryMock - = $this->getMock('Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterfaceFactory', $methods, [], '', false); - $this->appliedTaxDataObjectFactoryMock->expects($this->any()) + + $className = 'Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterfaceFactory'; + $appliedTaxDataObjectFactoryMock = $this->getMock($className, $methods, [], '', false); + $appliedTaxDataObjectFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->appliedTaxDataObject); - $this->itemDataObject = $objectManager->getObject('Magento\Sales\Model\Order\Tax\Item'); - $this->itemDataObjectFactoryMock = - $this->getMock('Magento\Tax\Api\Data\OrderTaxDetailsItemInterfaceFactory', $methods, [], '', false); - $this->itemDataObjectFactoryMock->expects($this->atLeastOnce()) - ->method('create')->willReturn($this->itemDataObject); + $itemDataObject = $objectManager->getObject('Magento\Sales\Model\Order\Tax\Item'); + + $className = 'Magento\Tax\Api\Data\OrderTaxDetailsItemInterfaceFactory'; + $itemDataObjectFactoryMock = $this->getMock($className, $methods, [], '', false); + $itemDataObjectFactoryMock->expects($this->atLeastOnce()) + ->method('create') + ->willReturn($itemDataObject); $this->orderTaxDetailsDataObject = $objectManager->getObject('Magento\Tax\Model\Sales\Order\Details'); - $this->orderTaxDetailsDataObjectFactoryMock = - $this->getMock('Magento\Tax\Api\Data\OrderTaxDetailsInterfaceFactory', $methods, [], '', false); - $this->orderTaxDetailsDataObjectFactoryMock->expects($this->any()) + + $className = 'Magento\Tax\Api\Data\OrderTaxDetailsInterfaceFactory'; + $orderTaxDetailsDataObjectFactoryMock = $this->getMock($className, $methods, [], '', false); + $orderTaxDetailsDataObjectFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->orderTaxDetailsDataObject); $this->taxManagement = $objectManager->getObject( 'Magento\Tax\Model\Sales\Order\TaxManagement', [ - 'orderFactory' => $this->orderFactoryMock, - 'orderItemTaxFactory' => $this->taxItemFactoryMock, - 'appliedTaxDataObjectFactory' => $this->appliedTaxDataObjectFactoryMock, - 'itemDataObjectFactory' => $this->itemDataObjectFactoryMock, - 'orderTaxDetailsDataObjectFactory' => $this->orderTaxDetailsDataObjectFactoryMock + 'orderFactory' => $orderFactoryMock, + 'orderItemTaxFactory' => $taxItemFactoryMock, + 'orderTaxDetailsDataObjectFactory' => $orderTaxDetailsDataObjectFactoryMock, + 'itemDataObjectFactory' => $itemDataObjectFactoryMock, + 'appliedTaxDataObjectFactory' => $appliedTaxDataObjectFactoryMock ] ); } /** * @param array $orderItemAppliedTaxes + * @param array $expected * @return void * @dataProvider getOrderTaxDetailsDataProvider */ - public function testGetOrderTaxDetails($orderItemAppliedTaxes) + public function testGetOrderTaxDetails($orderItemAppliedTaxes, $expected) { $orderId = 1; - $data = $orderItemAppliedTaxes[0]; - - $this->orderFactoryMock->expects($this->atLeastOnce()) - ->method('create') - ->will($this->returnValue($this->orderMock)); $this->orderMock->expects($this->once()) ->method('load') ->with($orderId) ->will($this->returnSelf()); - $this->taxItemFactoryMock->expects($this->once())->method('create')->willReturn($this->taxItemResourceMock); $this->taxItemResourceMock->expects($this->once()) ->method('getTaxItemsByOrderId') ->with($orderId) ->will($this->returnValue($orderItemAppliedTaxes)); + $this->assertEquals($this->orderTaxDetailsDataObject, $this->taxManagement->getOrderTaxDetails($orderId)); - $this->assertEquals($data['code'], $this->appliedTaxDataObject->getCode()); - $this->assertEquals($data['title'], $this->appliedTaxDataObject->getTitle()); - $this->assertEquals($data['tax_percent'], $this->appliedTaxDataObject->getPercent()); - $this->assertEquals($data['real_amount'], $this->appliedTaxDataObject->getAmount()); - $this->assertEquals($data['real_base_amount'], $this->appliedTaxDataObject->getBaseAmount()); + + $this->assertEquals($expected['code'], $this->appliedTaxDataObject->getCode()); + $this->assertEquals($expected['title'], $this->appliedTaxDataObject->getTitle()); + $this->assertEquals($expected['tax_percent'], $this->appliedTaxDataObject->getPercent()); + $this->assertEquals($expected['real_amount'], $this->appliedTaxDataObject->getAmount()); + $this->assertEquals($expected['real_base_amount'], $this->appliedTaxDataObject->getBaseAmount()); } /** @@ -155,7 +125,7 @@ class TaxManagementTest extends \PHPUnit_Framework_TestCase */ public function getOrderTaxDetailsDataProvider() { - return [ + $data = [ 'one_item' => [ 'orderItemAppliedTaxes' => [ [ @@ -169,8 +139,16 @@ class TaxManagementTest extends \PHPUnit_Framework_TestCase 'real_base_amount' => '12.3779', ], ], + 'expected' => [ + 'code' => 'US-CA-*-Rate 1', + 'title' => 'US-CA-*-Rate 1', + 'tax_percent' => '8.25', + 'real_amount' => '6.1889', + 'real_base_amount' => '12.3779', + ], ], - 'wee_item' => [ + + 'weee_item' => [ 'orderItemAppliedTaxes' => [ [ 'item_id' => null, @@ -183,7 +161,15 @@ class TaxManagementTest extends \PHPUnit_Framework_TestCase 'real_base_amount' => '1.7979', ], ], + 'expected' => [ + 'code' => 'SanJose City Tax', + 'title' => 'SanJose City Tax', + 'tax_percent' => '6', + 'real_amount' => '0.9011', + 'real_base_amount' => '1.7979', + ], ], + 'shipping' => [ 'orderItemAppliedTaxes' => [ [ @@ -197,7 +183,48 @@ class TaxManagementTest extends \PHPUnit_Framework_TestCase 'real_base_amount' => '5.21', ], ], + 'expected' => [ + 'code' => 'Shipping', + 'title' => 'Shipping', + 'tax_percent' => '21', + 'real_amount' => '2.6', + 'real_base_amount' => '5.21', + ], + ], + + 'canadian_weee' => [ + 'orderItemAppliedTaxes' => [ + [ + 'item_id' => null, + 'taxable_item_type' => 'weee', + 'associated_item_id' => 69, + 'code' => 'GST', + 'title' => 'GST', + 'tax_percent' => '5', + 'real_amount' => '2.10', + 'real_base_amount' => '4.10', + ], + [ + 'item_id' => null, + 'taxable_item_type' => 'weee', + 'associated_item_id' => 69, + 'code' => 'GST', + 'title' => 'GST', + 'tax_percent' => '5', + 'real_amount' => '1.15', + 'real_base_amount' => '3.10', + ], + ], + 'expected' => [ + 'code' => 'GST', + 'title' => 'GST', + 'tax_percent' => '5', + 'real_amount' => '3.25', + 'real_base_amount' => '7.20', + ], ], ]; + + return $data; } } diff --git a/app/code/Magento/Weee/Model/Tax.php b/app/code/Magento/Weee/Model/Tax.php index d3de2f754ca00c37e76e58190bdf41b7232b5187..5a6d4ff73225725ade29f47599bd5130a62da49e 100644 --- a/app/code/Magento/Weee/Model/Tax.php +++ b/app/code/Magento/Weee/Model/Tax.php @@ -345,7 +345,7 @@ class Tax extends \Magento\Framework\Model\AbstractModel $one = new \Magento\Framework\DataObject(); $one->setName( - __($attribute['label_value']) ? __($attribute['label_value']) : __($attribute['frontend_label']) + $attribute['label_value'] ? __($attribute['label_value']) : __($attribute['frontend_label']) ) ->setAmount($amount) ->setTaxAmount($taxAmount) diff --git a/app/code/Magento/Weee/Test/Unit/Model/TaxTest.php b/app/code/Magento/Weee/Test/Unit/Model/TaxTest.php index b0ccb5e1890e940d897499aa1a8a703e89bdacdf..7d8b375821f73fb90b76fab024743d370c8e9d3b 100644 --- a/app/code/Magento/Weee/Test/Unit/Model/TaxTest.php +++ b/app/code/Magento/Weee/Test/Unit/Model/TaxTest.php @@ -16,6 +16,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase * @var \Magento\Weee\Model\Tax */ protected $model; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -93,7 +94,6 @@ class TaxTest extends \PHPUnit_Framework_TestCase { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $className = '\Magento\Framework\Model\Context'; $this->context = $this->getMock($className, [], [], '', false); @@ -158,10 +158,14 @@ class TaxTest extends \PHPUnit_Framework_TestCase ] ); } + /** * test GetProductWeeeAttributes + * @dataProvider getProductWeeeAttributesDataProvider + * @param array $weeeTaxCalculationsByEntity + * @param array $expectedFptLabel */ - public function testGetProductWeeeAttributes() + public function testGetProductWeeeAttributes($weeeTaxCalculationsByEntity, $expectedFptLabel) { $product = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false); $website = $this->getMock('\Magento\Store\Model\Website', [], [], '', false); @@ -233,11 +237,7 @@ class TaxTest extends \PHPUnit_Framework_TestCase $this->resource->expects($this->any()) ->method('fetchWeeeTaxCalculationsByEntity') ->willReturn([ - 0 => [ - 'weee_value' => 1, - 'label_value' => 'fpt_label', - 'attribute_code' => 'fpt_code', - ] + 0 => $weeeTaxCalculationsByEntity ]); $result = $this->model->getProductWeeeAttributes($product, null, null, null, true); @@ -246,6 +246,34 @@ class TaxTest extends \PHPUnit_Framework_TestCase $obj = $result[0]; $this->assertEquals(1, $obj->getAmount()); $this->assertEquals(0.25, $obj->getTaxAmount()); - $this->assertEquals('fpt_code', $obj->getCode()); + $this->assertEquals($weeeTaxCalculationsByEntity['attribute_code'], $obj->getCode()); + $this->assertEquals(__($expectedFptLabel), $obj->getName()); + } + + /** + * @return array + */ + public function getProductWeeeAttributesDataProvider() + { + return [ + 'store_label_defined' => [ + 'weeeTaxCalculationsByEntity' => [ + 'weee_value' => 1, + 'label_value' => 'fpt_label', + 'frontend_label' => 'fpt_label_frontend', + 'attribute_code' => 'fpt_code', + ], + 'expectedFptLabel' => 'fpt_label' + ], + 'store_label_not_defined' => [ + 'weeeTaxCalculationsByEntity' => [ + 'weee_value' => 1, + 'label_value' => '', + 'frontend_label' => 'fpt_label_frontend', + 'attribute_code' => 'fpt_code', + ], + 'expectedFptLabel' => 'fpt_label_frontend' + ] + ]; } } diff --git a/app/code/Magento/Weee/Ui/DataProvider/Product/Form/Modifier/Weee.php b/app/code/Magento/Weee/Ui/DataProvider/Product/Form/Modifier/Weee.php index 1285fbe3b0b8c8183cb38b79d7407494ec47880f..197a4d03cc231f271c33ede15730082a302bb80a 100644 --- a/app/code/Magento/Weee/Ui/DataProvider/Product/Form/Modifier/Weee.php +++ b/app/code/Magento/Weee/Ui/DataProvider/Product/Form/Modifier/Weee.php @@ -217,9 +217,6 @@ class Weee extends AbstractModifier ], 'caption' => '*', 'visible' => true, - 'validation' => [ - 'required-entry' => true - ], ], ], ], diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent.php index aadfdc9825f541fb408fbeffe7758ddf60b6e836..6741c685a3c7824ba7b5e90f7aca2ea4b9ad72ca 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent.php @@ -7,8 +7,11 @@ */ $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); +/** @var \Magento\SalesRule\Model\RuleFactory $salesRule */ +$salesRuleFactory = $objectManager->get('Magento\SalesRule\Model\RuleFactory'); + /** @var \Magento\SalesRule\Model\Rule $salesRule */ -$salesRule = $objectManager->create('Magento\SalesRule\Model\Rule'); +$salesRule = $salesRuleFactory->create(); $data = [ 'name' => 'Test Coupon', @@ -27,5 +30,6 @@ $data = [ ]; $salesRule->loadPost($data)->setUseAutoGeneration(false)->save(); +$objectManager->get('Magento\Framework\Registry')->unregister('Magento/Checkout/_file/discount_10percent'); $objectManager->get('Magento\Framework\Registry') - ->register('Magento/Checkout/_file/discount_10percent', $salesRule->getRuleId(), true); + ->register('Magento/Checkout/_file/discount_10percent', $salesRule->getRuleId()); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php index e89c11ac5a2f2e565885a0d1491ddb2a74b9db4f..697d15ea5e1e6711a0d765cc7ed8a1f087edf849 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers.php @@ -28,5 +28,6 @@ $data = [ ]; $salesRule->loadPost($data)->setUseAutoGeneration(false)->save(); +$objectManager->get('Magento\Framework\Registry')->unregister('Magento/Checkout/_file/discount_10percent_generalusers'); $objectManager->get('Magento\Framework\Registry') - ->register('Magento/Checkout/_file/discount_10percent_generalusers', $salesRule->getRuleId(), true); + ->register('Magento/Checkout/_file/discount_10percent_generalusers', $salesRule->getRuleId()); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers_rollback.php index a6f462f767443532421f66b9e8d144335469233e..d935c7b7f3b5149fa0771be075269b4359e859f1 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_generalusers_rollback.php @@ -8,5 +8,8 @@ /** @var \Magento\SalesRule\Model\Rule $salesRule */ $salesRule = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\SalesRule\Model\Rule'); -$salesRule->load('Test Coupon for General', 'name'); +/** @var int $salesRuleId */ +$salesRuleId = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry') + ->registry('Magento/Checkout/_file/discount_10percent_generalusers'); +$salesRule->load($salesRuleId); $salesRule->delete(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_rollback.php index 53c90ee1778f1eb0c67b16c1af81e4a87f9cb47f..d27c7a86de5125fe2b716ceb191314487870228c 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/discount_10percent_rollback.php @@ -8,5 +8,8 @@ /** @var \Magento\SalesRule\Model\Rule $salesRule */ $salesRule = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\SalesRule\Model\Rule'); -$salesRule->load('Test Coupon', 'name'); +/** @var int $salesRuleId */ +$salesRuleId = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry') + ->registry('Magento/Checkout/_file/discount_10percent'); +$salesRule->load($salesRuleId); $salesRule->delete(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved.php index c35b5769fc9d3596f1d8429dd099233e28c7117d..54993e76f98fe32e93da770acc5d76d38dcdfee1 100644 --- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved.php +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_coupon_saved.php @@ -13,7 +13,8 @@ require __DIR__ . '/../../Checkout/_files/discount_10percent.php'; require 'quote_with_address_saved.php'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); -$salesRule = $objectManager->create('Magento\SalesRule\Model\Rule'); +$salesRuleFactory = $objectManager->get('Magento\SalesRule\Model\RuleFactory'); +$salesRule = $salesRuleFactory->create(); $salesRuleId = $objectManager->get('Magento\Framework\Registry') ->registry('Magento/Checkout/_file/discount_10percent'); $salesRule->load($salesRuleId);