diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php index f1943bc108878..0daa1dfb5c8eb 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/TierPrice/UpdateHandler.php @@ -96,12 +96,7 @@ public function execute($entity, $arguments = []) $productId = (int)$entity->getData($identifierField); // prepare original data to compare - $origPrices = []; - $originalId = $entity->getOrigData($identifierField); - if (empty($originalId) || $entity->getData($identifierField) == $originalId) { - $origPrices = $entity->getOrigData($attribute->getName()); - } - + $origPrices = $entity->getOrigData($attribute->getName()); $old = $this->prepareOldTierPriceToCompare($origPrices); // prepare data for save $new = $this->prepareNewDataForSave($priceRows, $isGlobal); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php index cce00c50d37af..fde793d5c5f89 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Attribute/Backend/TierPrice/UpdateHandlerTest.php @@ -108,6 +108,7 @@ public function testExecute(): void ]; $linkField = 'entity_id'; $productId = 10; + $originalProductId = 11; /** @var \PHPUnit_Framework_MockObject_MockObject $product */ $product = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterface::class) @@ -124,7 +125,7 @@ public function testExecute(): void ->willReturnMap( [ ['tier_price', $originalTierPrices], - ['entity_id', $productId] + ['entity_id', $originalProductId] ] ); $product->expects($this->atLeastOnce())->method('getStoreId')->willReturn(0); diff --git a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php index 4c5f666805570..7fa674505461e 100644 --- a/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php +++ b/app/code/Magento/Multishipping/Model/Checkout/Type/Multishipping.php @@ -625,6 +625,7 @@ public function setShippingMethods($methods) $addressId = $address->getId(); if (isset($methods[$addressId])) { $address->setShippingMethod($methods[$addressId]); + $address->setCollectShippingRates(true); } elseif (!$address->getShippingMethod()) { throw new \Magento\Framework\Exception\LocalizedException( __('Set shipping methods for all addresses. Verify the shipping methods and try again.') diff --git a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php index 731365974c235..fba3245bec68d 100644 --- a/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php +++ b/app/code/Magento/Multishipping/Test/Unit/Model/Checkout/Type/MultishippingTest.php @@ -420,13 +420,16 @@ public function testSetShippingMethods() $methodsArray = [1 => 'flatrate_flatrate', 2 => 'tablerate_bestway']; $addressId = 1; $addressMock = $this->getMockBuilder(QuoteAddress::class) - ->setMethods(['getId', 'setShippingMethod']) + ->setMethods(['getId', 'setShippingMethod', 'setCollectShippingRates']) ->disableOriginalConstructor() ->getMock(); $addressMock->expects($this->once())->method('getId')->willReturn($addressId); $this->quoteMock->expects($this->once())->method('getAllShippingAddresses')->willReturn([$addressMock]); $addressMock->expects($this->once())->method('setShippingMethod')->with($methodsArray[$addressId]); + $addressMock->expects($this->once()) + ->method('setCollectShippingRates') + ->with(true); $this->quoteMock->expects($this->once()) ->method('__call') ->with('setTotalsCollectedFlag', [false]) diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php index d4c2e7b2d6854..95dace13d832f 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php @@ -41,7 +41,7 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo) $baseOrderItemTax = (double)$orderItem->getBaseTaxInvoiced(); $orderItemQty = (double)$orderItem->getQtyInvoiced(); - if ($orderItemTax && $orderItemQty) { + if ($orderItemQty) { /** * Check item tax amount */ diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php index 565d51ff515a2..f32ce7aa4715b 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php @@ -100,16 +100,18 @@ public function testCollect($orderData, $creditmemoData, $expectedResults) } $this->creditmemo->expects($this->any()) ->method('roundPrice') - ->will($this->returnCallback( - function ($price, $type) use (&$roundingDelta) { - if (!isset($roundingDelta[$type])) { - $roundingDelta[$type] = 0; + ->will( + $this->returnCallback( + function ($price, $type) use (&$roundingDelta) { + if (!isset($roundingDelta[$type])) { + $roundingDelta[$type] = 0; + } + $roundedPrice = round($price + $roundingDelta[$type], 2); + $roundingDelta[$type] = $price - $roundedPrice; + return $roundedPrice; } - $roundedPrice = round($price + $roundingDelta[$type], 2); - $roundingDelta[$type] = $price - $roundedPrice; - return $roundedPrice; - } - )); + ) + ); $this->model->collect($this->creditmemo); @@ -610,6 +612,143 @@ public function collectDataProvider() ], ]; + // scenario 6: 2 items, 2 invoiced, price includes tax, full discount, free shipping + // partial credit memo, make sure that discount tax compensation (with 100 % discount) is calculated correctly + $result['collect_with_full_discount_product_price'] = [ + 'order_data' => [ + 'data_fields' => [ + 'discount_amount' => -200.00, + 'discount_invoiced' => -200.00, + 'subtotal' => 181.82, + 'subtotal_incl_tax' => 200, + 'base_subtotal' => 181.82, + 'base_subtotal_incl_tax' => 200, + 'subtotal_invoiced' => 181.82, + 'discount_tax_compensation_amount' => 18.18, + 'discount_tax_compensation_invoiced' => 18.18, + 'base_discount_tax_compensation_amount' => 18.18, + 'base_discount_tax_compensation_invoiced' => 18.18, + 'grand_total' => 0, + 'base_grand_total' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, + 'tax_amount' => 0, + 'base_tax_amount' => 0, + 'tax_invoiced' => 0, + 'base_tax_invoiced' => 0, + 'tax_refunded' => 0, + 'base_tax_refunded' => 0, + 'base_shipping_amount' => 0, + ], + ], + 'creditmemo_data' => [ + 'items' => [ + 'item_1' => [ + 'order_item' => [ + 'qty_invoiced' => 1, + 'tax_amount' => 0, + 'tax_invoiced' => 0, + 'tax_refunded' => null, + 'base_tax_amount' => 0, + 'base_tax_invoiced' => 0, + 'base_tax_refunded' => 0, + 'tax_percent' => 10, + 'qty_refunded' => 0, + 'discount_percent' => 100, + 'discount_amount' => 100, + 'base_discount_amount' => 100, + 'discount_invoiced' => 100, + 'base_discount_invoiced' => 100, + 'row_total' => 90.91, + 'base_row_total' => 90.91, + 'row_invoiced' => 90.91, + 'base_row_invoiced' => 90.91, + 'price_incl_tax' => 100, + 'base_price_incl_tax' => 100, + 'row_total_incl_tax' => 100, + 'base_row_total_incl_tax' => 100, + 'discount_tax_compensation_amount' => 9.09, + 'base_discount_tax_compensation_amount' => 9.09, + 'discount_tax_compensation_invoiced' => 9.09, + 'base_discount_tax_compensation_invoiced' => 9.09, + ], + 'is_last' => true, + 'qty' => 1, + ], + 'item_2' => [ + 'order_item' => [ + 'qty_invoiced' => 1, + 'tax_amount' => 0, + 'tax_invoiced' => 0, + 'tax_refunded' => null, + 'base_tax_amount' => 0, + 'base_tax_invoiced' => 0, + 'base_tax_refunded' => null, + 'tax_percent' => 10, + 'qty_refunded' => 0, + 'discount_percent' => 100, + 'discount_amount' => 100, + 'base_discount_amount' => 100, + 'discount_invoiced' => 100, + 'base_discount_invoiced' => 100, + 'row_total' => 90.91, + 'base_row_total' => 90.91, + 'row_invoiced' => 90.91, + 'base_row_invoiced' => 90.91, + 'price_incl_tax' => 100, + 'base_price_incl_tax' => 100, + 'row_total_incl_tax' => 100, + 'base_row_total_incl_tax' => 100, + 'discount_tax_compensation_amount' => 9.09, + 'base_discount_tax_compensation_amount' => 9.09, + 'discount_tax_compensation_invoiced' => 9.09, + 'base_discount_tax_compensation_invoiced' => 9.09, + ], + 'is_last' => false, + 'qty' => 0, + ], + ], + 'is_last' => false, + 'data_fields' => [ + 'grand_total' => -9.09, + 'base_grand_total' => -9.09, + 'base_shipping_amount' => 0, + 'tax_amount' => 0, + 'base_tax_amount' => 0, + 'invoice' => new MagentoObject( + [ + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + 'shipping_discount_tax_compensation_amount' => 0, + 'base_shipping_discount_tax_compensation_amount' => 0, + ] + ), + ], + ], + 'expected_results' => [ + 'creditmemo_items' => [ + 'item_1' => [ + 'tax_amount' => 0, + 'base_tax_amount' => 0, + ], + 'item_2' => [ + 'tax_amount' => 0, + 'base_tax_amount' => 0, + ], + ], + 'creditmemo_data' => [ + 'grand_total' => 0, + 'base_grand_total' => 0, + 'tax_amount' => 0, + 'base_tax_amount' => 0, + 'shipping_tax_amount' => 0, + 'base_shipping_tax_amount' => 0, + ], + ], + ]; + return $result; } diff --git a/app/code/Magento/Sitemap/Model/Sitemap.php b/app/code/Magento/Sitemap/Model/Sitemap.php index 0d69634ccfa5e..2baa6ff2c71a7 100644 --- a/app/code/Magento/Sitemap/Model/Sitemap.php +++ b/app/code/Magento/Sitemap/Model/Sitemap.php @@ -10,6 +10,7 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Filesystem; use Magento\Framework\UrlInterface; use Magento\Robots\Model\Config\Value; use Magento\Sitemap\Model\ItemProvider\ItemProviderInterface; @@ -191,6 +192,16 @@ class Sitemap extends \Magento\Framework\Model\AbstractModel implements \Magento */ private $lastModMinTsVal; + /** + * @var Filesystem + */ + private $filesystem; + + /** + * @var DocumentRoot + */ + private $documentRoot; + /** * Initialize dependencies. * @@ -238,8 +249,9 @@ public function __construct( ) { $this->_escaper = $escaper; $this->_sitemapData = $sitemapData; - $documentRoot = $documentRoot ?: ObjectManager::getInstance()->get(DocumentRoot::class); - $this->_directory = $filesystem->getDirectoryWrite($documentRoot->getPath()); + $this->documentRoot = $documentRoot ?: ObjectManager::getInstance()->get(DocumentRoot::class); + $this->filesystem = $filesystem; + $this->_directory = $filesystem->getDirectoryWrite($this->documentRoot->getPath()); $this->_categoryFactory = $categoryFactory; $this->_productFactory = $productFactory; $this->_cmsFactory = $cmsFactory; @@ -727,8 +739,8 @@ protected function _getFormattedLastmodDate($date) */ protected function _getDocumentRoot() { - // phpcs:ignore Magento2.Functions.DiscouragedFunction - return realpath($this->_request->getServer('DOCUMENT_ROOT')); + return $this->filesystem->getDirectoryRead($this->documentRoot->getPath()) + ->getAbsolutePath(); } /** diff --git a/dev/tests/integration/testsuite/Magento/Sitemap/Model/SitemapTest.php b/dev/tests/integration/testsuite/Magento/Sitemap/Model/SitemapTest.php new file mode 100644 index 0000000000000..73863e0915c66 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sitemap/Model/SitemapTest.php @@ -0,0 +1,70 @@ +objectManager = Bootstrap::getObjectManager(); + $this->model = $this->objectManager->get(Sitemap::class); + $this->filesystem = $this->objectManager->get(Filesystem::class); + } + + /** + * Test get sitemap URL from parent root directory path + * + * @return void + */ + public function testGetSitemapUrlFromParentRootDirectoryPath(): void + { + $rootDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT) + ->getAbsolutePath(); + $requestPath = dirname($rootDir); + + /** @var Request $request */ + $request = $this->objectManager->get(Request::class); + //imitation run script from parent root directory + $request->setServer(new Parameters(['DOCUMENT_ROOT' => $requestPath])); + + $sitemapUrl = $this->model->getSitemapUrl('/', 'sitemap.xml'); + + $this->assertEquals('http://localhost/sitemap.xml', $sitemapUrl); + } +}