From 7f48d52d350d3ec11da8f160dbca10e530acba0b Mon Sep 17 00:00:00 2001 From: Andrii Voskoboinikov Date: Fri, 18 Nov 2016 11:01:51 +0200 Subject: [PATCH 01/43] MAGETWO-60428: Production mode is not enabled on Bamboo - 2.0 --- .../ObjectManager/Config/Compiled.php | 26 +++- .../ObjectManager/Config/CompiledTest.php | 129 ++++++++++++++++++ 2 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 lib/internal/Magento/Framework/Test/Unit/ObjectManager/Config/CompiledTest.php diff --git a/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php b/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php index 227b9444b6061..be3eda5359c10 100644 --- a/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php +++ b/lib/internal/Magento/Framework/ObjectManager/Config/Compiled.php @@ -1,15 +1,15 @@ arguments[$type]; } else { - return [['_i_' => 'Magento\Framework\ObjectManagerInterface']]; + return [['_i_' => \Magento\Framework\ObjectManagerInterface::class]]; } } @@ -129,9 +129,23 @@ public function getPreference($type) */ public function extend(array $configuration) { - $this->arguments = $configuration['arguments']; - $this->virtualTypes = $configuration['instanceTypes']; - $this->preferences = $configuration['preferences']; + $this->arguments = isset($configuration['arguments']) + ? array_replace( + $this->arguments ?: [], + $configuration['arguments'] + ) : $this->arguments; + + $this->virtualTypes = isset($configuration['instanceTypes']) + ? array_replace( + $this->virtualTypes ?: [], + $configuration['instanceTypes'] + ) : $this->virtualTypes; + + $this->preferences = isset($configuration['preferences']) + ? array_replace( + $this->preferences ?: [], + $configuration['preferences'] + ) : $this->preferences; } /** diff --git a/lib/internal/Magento/Framework/Test/Unit/ObjectManager/Config/CompiledTest.php b/lib/internal/Magento/Framework/Test/Unit/ObjectManager/Config/CompiledTest.php new file mode 100644 index 0000000000000..8a899070760c7 --- /dev/null +++ b/lib/internal/Magento/Framework/Test/Unit/ObjectManager/Config/CompiledTest.php @@ -0,0 +1,129 @@ +objectManagerHelper = new ObjectManagerHelper($this); + } + + /** + * @param array $initialData + * @param array $configuration + * @param array $expectedArguments + * @param array $expectedVirtualTypes + * @param array $expectedPreferences + * + * @dataProvider extendDataProvider + */ + public function testExtend( + array $initialData, + array $configuration, + array $expectedArguments, + array $expectedVirtualTypes, + array $expectedPreferences + ) { + /** @var CompiledConfig $compiledConfig */ + $compiledConfig = $this->objectManagerHelper->getObject(CompiledConfig::class, ['data' => $initialData]); + $compiledConfig->extend($configuration); + + foreach ($expectedArguments as $type => $arguments) { + $this->assertEquals($arguments, $compiledConfig->getArguments($type)); + } + + $this->assertEquals($expectedVirtualTypes, $compiledConfig->getVirtualTypes()); + $this->assertEquals($expectedPreferences, $compiledConfig->getPreferences()); + } + + /** + * @return array + */ + public function extendDataProvider() + { + return [ + [ + 'initialData' => [ + 'arguments' => [ + 'type1' => serialize(['argument1_1' => 'argumentValue1_1', 'argument1_2' => 'argumentValue1_2']) + ], + 'instanceTypes' => [ + 'instanceType1' => 'instanceTypeValue1', 'instanceType2' => 'instanceTypeValue2' + ], + 'preferences' => [ + 'preference1' => 'preferenceValue1', + 'preference2' => 'preferenceValue2' + ] + ], + 'configuration' => [ + 'arguments' => [ + 'type1' => serialize(['argument1_1' => 'newArgumentValue1_1']), + 'type2' => serialize(['argument2_1' => 'newArgumentValue2_1']) + ], + 'instanceTypes' => [ + 'instanceType2' => 'newInstanceTypeValue2', + 'instanceType3' => 'newInstanceTypeValue3' + ], + 'preferences' => [ + 'preference1' => 'newPreferenceValue1' + ] + ], + 'expectedArguments' => [ + 'type1' => ['argument1_1' => 'newArgumentValue1_1'], + 'type2' => ['argument2_1' => 'newArgumentValue2_1'] + ], + 'expectedVirtualTypes' => [ + 'instanceType1' => 'instanceTypeValue1', + 'instanceType2' => 'newInstanceTypeValue2', + 'instanceType3' => 'newInstanceTypeValue3' + ], + 'expectedPreferences' => [ + 'preference1' => 'newPreferenceValue1', + 'preference2' => 'preferenceValue2' + ] + ], + + [ + 'initialData' => [ + 'arguments' => null, + 'instanceTypes' => null, + 'preferences' => null + ], + 'configuration' => [ + 'arguments' => [ + 'type1' => serialize(['argument1_1' => 'newArgumentValue1_1']), + 'type2' => serialize(['argument2_1' => 'newArgumentValue2_1']) + ], + 'instanceTypes' => [ + 'instanceType2' => 'newInstanceTypeValue2', + 'instanceType3' => 'newInstanceTypeValue3' + ], + 'preferences' => ['preference1' => 'newPreferenceValue1'] + ], + 'expectedArguments' => [ + 'type1' => ['argument1_1' => 'newArgumentValue1_1'], + 'type2' => ['argument2_1' => 'newArgumentValue2_1'] + ], + 'expectedVirtualTypes' => [ + 'instanceType2' => 'newInstanceTypeValue2', + 'instanceType3' => 'newInstanceTypeValue3' + ], + 'expectedPreferences' => [ + 'preference1' => 'newPreferenceValue1' + ] + ] + ]; + } +} From 13dc0420523d410e5a6ce2895e299d924167720c Mon Sep 17 00:00:00 2001 From: Sviatoslav Mankivskyi Date: Thu, 24 Nov 2016 18:01:05 +0200 Subject: [PATCH 02/43] MAGETWO-61249: [Backport] Loader doesn't disappear after click on 'Place Order' button - for 2.0 --- .../Controller/Directpost/Payment/Place.php | 2 +- .../Directpost/Payment/PlaceTest.php | 2 +- app/code/Magento/Authorizenet/i18n/en_US.csv | 1 + .../method-renderer/payflowpro-method.js | 26 ++++++++++++------- .../Magento/Quote/Model/QuoteManagement.php | 2 +- app/code/Magento/Quote/i18n/en_US.csv | 1 + 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php index 7f229d87cc275..0ffe6df37b1f0 100644 --- a/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php +++ b/app/code/Magento/Authorizenet/Controller/Directpost/Payment/Place.php @@ -127,7 +127,7 @@ protected function placeCheckoutOrder() ); } catch (\Exception $exception) { $result->setData('error', true); - $result->setData('error_messages', __('Cannot place order.')); + $result->setData('error_messages', __('Unable to place order. Please try again later.')); } if ($response instanceof Http) { $response->representJson($this->jsonHelper->jsonEncode($result)); diff --git a/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php b/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php index bb423bc8d54d7..ee0911ca68158 100644 --- a/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php +++ b/app/code/Magento/Authorizenet/Test/Unit/Controller/Directpost/Payment/PlaceTest.php @@ -279,7 +279,7 @@ public function textExecuteFailedPlaceOrderDataProvider() { $objectFailed = new \Magento\Framework\DataObject(); $objectFailed->setData('error', true); - $objectFailed->setData('error_messages', __('Cannot place order.')); + $objectFailed->setData('error_messages', __('Unable to place order. Please try again later.')); return [ [ diff --git a/app/code/Magento/Authorizenet/i18n/en_US.csv b/app/code/Magento/Authorizenet/i18n/en_US.csv index 7bbbbaf286d5a..d77495536d108 100644 --- a/app/code/Magento/Authorizenet/i18n/en_US.csv +++ b/app/code/Magento/Authorizenet/i18n/en_US.csv @@ -13,6 +13,7 @@ Cancel,Cancel "Something went wrong canceling the transactions.","Something went wrong canceling the transactions." "There was an error canceling transactions. Please contact us or try again later.","There was an error canceling transactions. Please contact us or try again later." "We couldn't process your order right now. Please try again later.","We couldn't process your order right now. Please try again later." +"Unable to place order. Please try again later.","Unable to place order. Please try again later." "amount %1","amount %1" failed,failed successful,successful diff --git a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/payflowpro-method.js b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/payflowpro-method.js index 5f5695b2bad5d..cd53ddcf49148 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/payflowpro-method.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/payflowpro-method.js @@ -52,18 +52,24 @@ define( var self = this; if (this.validateHandler() && additionalValidators.validate()) { - fullScreenLoader.startLoader(); this.isPlaceOrderActionAllowed(false); - $.when(setPaymentInformationAction(this.messageContainer, { - 'method': self.getCode() - })).done(function () { - self.placeOrderHandler().fail(function () { + fullScreenLoader.startLoader(); + $.when( + setPaymentInformationAction(this.messageContainer, {'method': self.getCode()}) + ).done( + function () { + self.placeOrderHandler().fail( + function () { + fullScreenLoader.stopLoader(); + } + ); + } + ).always( + function () { + self.isPlaceOrderActionAllowed(true); fullScreenLoader.stopLoader(); - }); - }).fail(function () { - fullScreenLoader.stopLoader(); - self.isPlaceOrderActionAllowed(true); - }); + } + ); } } }); diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index dcec33d999e32..4292d379e3f35 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -354,7 +354,7 @@ public function placeOrder($cartId, PaymentInterface $paymentMethod = null) $order = $this->submit($quote); if (null == $order) { - throw new LocalizedException(__('Cannot place order.')); + throw new LocalizedException(__('Unable to place order. Please try again later.')); } $this->checkoutSession->setLastQuoteId($quote->getId()); diff --git a/app/code/Magento/Quote/i18n/en_US.csv b/app/code/Magento/Quote/i18n/en_US.csv index 9e7925f16e2e2..cd6aa292c2128 100644 --- a/app/code/Magento/Quote/i18n/en_US.csv +++ b/app/code/Magento/Quote/i18n/en_US.csv @@ -29,3 +29,4 @@ Shipping,Shipping "Please specify a shipping method.","Please specify a shipping method." "Please check the billing address information. %1","Please check the billing address information. %1" "Please select a valid payment method.","Please select a valid payment method." +"Unable to place order. Please try again later.","Unable to place order. Please try again later." From b385d4064e38b47366719a0524576fbd8e574416 Mon Sep 17 00:00:00 2001 From: Olga Nakonechna Date: Fri, 25 Nov 2016 12:11:07 +0200 Subject: [PATCH 03/43] MAGETWO-61268: [Backport] - Creditmemo return to stock only one unit of configurable product - for 2.0.11 --- .../Magento/CatalogInventory/etc/events.xml | 3 - .../Adminhtml/Order/CreditmemoLoader.php | 4 +- .../Sales/Model/Order/CreditmemoFactory.php | 54 +++++++- .../Model/Order/ReturnProcessor.php | 45 +------ .../Observer/RefundOrderInventoryObserver.php | 67 +++++----- .../Unit/Model/Order/ReturnProcessorTest.php | 32 ++--- .../RefundOrderInventoryObserverTest.php | 103 +++++++++++---- .../Magento/SalesInventory/etc/events.xml | 12 ++ ...sertProductQtyDecreasedAfterCreditmemo.php | 118 ++++++++++++++++++ .../Test/Repository/ConfigurableProduct.xml | 35 +++++- .../TestCase/CreateCreditMemoEntityTest.xml | 21 ++++ ...sertProductQtyDecreasedAfterCreditmemo.php | 110 ++++++++++++++++ .../TestCase/CreateCreditMemoEntityTest.php | 25 ---- .../TestCase/CreateCreditMemoEntityTest.xml | 2 +- 14 files changed, 483 insertions(+), 148 deletions(-) rename app/code/Magento/{CatalogInventory => SalesInventory}/Observer/RefundOrderInventoryObserver.php (57%) rename app/code/Magento/{CatalogInventory => SalesInventory}/Test/Unit/Observer/RefundOrderInventoryObserverTest.php (62%) create mode 100644 app/code/Magento/SalesInventory/etc/events.xml create mode 100644 dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php create mode 100644 dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml create mode 100644 dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php diff --git a/app/code/Magento/CatalogInventory/etc/events.xml b/app/code/Magento/CatalogInventory/etc/events.xml index a1476c2c3f8b1..d9db59b7a1766 100644 --- a/app/code/Magento/CatalogInventory/etc/events.xml +++ b/app/code/Magento/CatalogInventory/etc/events.xml @@ -33,9 +33,6 @@ - - - diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php index 36f1310079ed5..ac3ffdc3d622c 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php @@ -217,9 +217,9 @@ public function load() foreach ($creditmemo->getAllItems() as $creditmemoItem) { $orderItem = $creditmemoItem->getOrderItem(); $parentId = $orderItem->getParentItemId(); - if (isset($backToStock[$orderItem->getId()])) { + if ($parentId && isset($backToStock[$parentId]) && $backToStock[$parentId]) { $creditmemoItem->setBackToStock(true); - } elseif ($orderItem->getParentItem() && isset($backToStock[$parentId]) && $backToStock[$parentId]) { + } elseif (isset($backToStock[$orderItem->getId()])) { $creditmemoItem->setBackToStock(true); } elseif (empty($savedData)) { $creditmemoItem->setBackToStock( diff --git a/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php b/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php index 21104933a51d6..ff687074e4a66 100644 --- a/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php +++ b/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php @@ -3,7 +3,6 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Sales\Model\Order; /** @@ -23,6 +22,11 @@ class CreditmemoFactory */ protected $taxConfig; + /** + * @var \Magento\Framework\Unserialize\Unserialize + */ + protected $unserialize; + /** * Factory constructor * @@ -57,7 +61,12 @@ public function createByOrder(\Magento\Sales\Model\Order $order, array $data = [ $item = $this->convertor->itemToCreditmemoItem($orderItem); if ($orderItem->isDummy()) { - $qty = 1; + if (isset($data['qtys'][$orderItem->getParentItemId()])) { + $parentQty = $data['qtys'][$orderItem->getParentItemId()]; + } else { + $parentQty = $orderItem->getParentItem() ? $orderItem->getParentItem()->getQtyToRefund() : 1; + } + $qty = $this->calculateProductOptions($orderItem, $parentQty); $orderItem->setLockedDoShip(true); } else { if (isset($qtys[$orderItem->getId()])) { @@ -132,7 +141,12 @@ public function createByInvoice(\Magento\Sales\Model\Order\Invoice $invoice, arr $item = $this->convertor->itemToCreditmemoItem($orderItem); if ($orderItem->isDummy()) { - $qty = 1; + if (isset($data['qtys'][$orderItem->getParentItemId()])) { + $parentQty = $data['qtys'][$orderItem->getParentItemId()]; + } else { + $parentQty = $orderItem->getParentItem() ? $orderItem->getParentItem()->getQtyToRefund() : 1; + } + $qty = $this->calculateProductOptions($orderItem, $parentQty); } else { if (isset($qtys[$orderItem->getId()])) { $qty = (double)$qtys[$orderItem->getId()]; @@ -245,4 +259,38 @@ protected function initData($creditmemo, $data) $creditmemo->setAdjustmentNegative($data['adjustment_negative']); } } + + /** + * @param \Magento\Sales\Api\Data\OrderItemInterface $orderItem + * @param array $qtys + * @return int + */ + private function calculateProductOptions(\Magento\Sales\Api\Data\OrderItemInterface $orderItem, $parentQty) + { + $qty = $parentQty; + $productOptions = $orderItem->getProductOptions(); + if (isset($productOptions['bundle_selection_attributes'])) { + $bundleSelectionAttributes = $this->getUnserialize() + ->unserialize($productOptions['bundle_selection_attributes']); + if ($bundleSelectionAttributes) { + $qty = $bundleSelectionAttributes['qty'] * $parentQty; + } + } + return $qty; + } + + /** + * Get Unserialize + * + * @return \Magento\Framework\Unserialize\Unserialize + * @deprecated + */ + private function getUnserialize() + { + if (!$this->unserialize) { + $this->unserialize = \Magento\Framework\App\ObjectManager::getInstance() + ->get(\Magento\Framework\Unserialize\Unserialize::class); + } + return $this->unserialize; + } } diff --git a/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php b/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php index 7752d7131031c..3680bbb3a1eae 100644 --- a/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php +++ b/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php @@ -6,7 +6,6 @@ namespace Magento\SalesInventory\Model\Order; use Magento\Sales\Api\Data\CreditmemoInterface; -use Magento\Sales\Api\Data\CreditmemoItemInterface; use Magento\Sales\Api\Data\OrderInterface; /** @@ -29,52 +28,35 @@ class ReturnProcessor */ private $priceIndexer; - /** - * @var \Magento\Sales\Api\CreditmemoRepositoryInterface - */ - private $creditmemoRepository; - /** * @var \Magento\Store\Model\StoreManagerInterface */ private $storeManager; - /** - * @var \Magento\Sales\Api\OrderRepositoryInterface - */ - private $orderRepository; - /** * @var \Magento\Sales\Api\OrderItemRepositoryInterface */ private $orderItemRepository; /** - * ReturnToStockPlugin constructor. - * @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration + * ReturnProcessor constructor. * @param \Magento\CatalogInventory\Api\StockManagementInterface $stockManagement * @param \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexer * @param \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer - * @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository * @param \Magento\Sales\Api\OrderItemRepositoryInterface $orderItemRepository */ public function __construct( \Magento\CatalogInventory\Api\StockManagementInterface $stockManagement, \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexer, \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer, - \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Sales\Api\OrderItemRepositoryInterface $orderItemRepository ) { $this->stockManagement = $stockManagement; $this->stockIndexerProcessor = $stockIndexer; $this->priceIndexer = $priceIndexer; - $this->creditmemoRepository = $creditmemoRepository; $this->storeManager = $storeManager; - $this->orderRepository = $orderRepository; $this->orderItemRepository = $orderItemRepository; } @@ -82,22 +64,22 @@ public function __construct( * @param CreditmemoInterface $creditmemo * @param OrderInterface $order * @param array $returnToStockItems + * @param bool $isAutoReturn * @return void */ public function execute( CreditmemoInterface $creditmemo, OrderInterface $order, - array $returnToStockItems = [] + array $returnToStockItems = [], + $isAutoReturn = false ) { $itemsToUpdate = []; foreach ($creditmemo->getItems() as $item) { - $qty = $item->getQty(); $productId = $item->getProductId(); $orderItem = $this->orderItemRepository->get($item->getOrderItemId()); $parentItemId = $orderItem->getParentItemId(); - if ($this->canReturnItem($item, $qty, $parentItemId, $returnToStockItems)) { - $parentItem = $parentItemId ? $this->getItemByOrderId($creditmemo, $parentItemId) : false; - $qty = $parentItem ? $parentItem->getQty() * $qty : $qty; + $qty = $item->getQty(); + if ($isAutoReturn || $this->canReturnItem($item, $qty, $parentItemId, $returnToStockItems)) { if (isset($itemsToUpdate[$productId])) { $itemsToUpdate[$productId] += $qty; } else { @@ -122,21 +104,6 @@ public function execute( } } - /** - * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo - * @param int $parentItemId - * @return bool|CreditmemoItemInterface - */ - private function getItemByOrderId(\Magento\Sales\Api\Data\CreditmemoInterface $creditmemo, $parentItemId) - { - foreach ($creditmemo->getItems() as $item) { - if ($item->getOrderItemId() == $parentItemId) { - return $item; - } - } - return false; - } - /** * @param \Magento\Sales\Api\Data\CreditmemoItemInterface $item * @param int $qty diff --git a/app/code/Magento/CatalogInventory/Observer/RefundOrderInventoryObserver.php b/app/code/Magento/SalesInventory/Observer/RefundOrderInventoryObserver.php similarity index 57% rename from app/code/Magento/CatalogInventory/Observer/RefundOrderInventoryObserver.php rename to app/code/Magento/SalesInventory/Observer/RefundOrderInventoryObserver.php index 9702bfc7cfe42..acdebcf976a2e 100644 --- a/app/code/Magento/CatalogInventory/Observer/RefundOrderInventoryObserver.php +++ b/app/code/Magento/SalesInventory/Observer/RefundOrderInventoryObserver.php @@ -4,54 +4,74 @@ * See COPYING.txt for license details. */ -namespace Magento\CatalogInventory\Observer; +namespace Magento\SalesInventory\Observer; use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\CatalogInventory\Api\StockManagementInterface; use Magento\Framework\Event\Observer as EventObserver; use Magento\Framework\Event\ObserverInterface; +use Magento\Sales\Model\OrderRepository; +use Magento\SalesInventory\Model\Order\ReturnProcessor; /** * Catalog inventory module observer + * @deprecated */ class RefundOrderInventoryObserver implements ObserverInterface { /** * @var StockConfigurationInterface */ - protected $stockConfiguration; + private $stockConfiguration; /** * @var StockManagementInterface */ - protected $stockManagement; + private $stockManagement; /** * @var \Magento\CatalogInventory\Model\Indexer\Stock\Processor */ - protected $stockIndexerProcessor; + private $stockIndexerProcessor; /** * @var \Magento\Catalog\Model\Indexer\Product\Price\Processor */ - protected $priceIndexer; + private $priceIndexer; /** + * @var \Magento\SalesInventory\Model\Order\ReturnProcessor + */ + private $returnProcessor; + + /** + * @var \Magento\Sales\Api\OrderRepositoryInterface + */ + private $orderRepository; + + /** + * RefundOrderInventoryObserver constructor. * @param StockConfigurationInterface $stockConfiguration * @param StockManagementInterface $stockManagement * @param \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor * @param \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer + * @param ReturnProcessor $returnProcessor + * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository */ public function __construct( StockConfigurationInterface $stockConfiguration, StockManagementInterface $stockManagement, \Magento\CatalogInventory\Model\Indexer\Stock\Processor $stockIndexerProcessor, - \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer + \Magento\Catalog\Model\Indexer\Product\Price\Processor $priceIndexer, + \Magento\SalesInventory\Model\Order\ReturnProcessor $returnProcessor, + \Magento\Sales\Api\OrderRepositoryInterface $orderRepository ) { $this->stockConfiguration = $stockConfiguration; $this->stockManagement = $stockManagement; $this->stockIndexerProcessor = $stockIndexerProcessor; $this->priceIndexer = $priceIndexer; + $this->returnProcessor = $returnProcessor; + $this->orderRepository = $orderRepository; } /** @@ -64,31 +84,18 @@ public function execute(EventObserver $observer) { /* @var $creditmemo \Magento\Sales\Model\Order\Creditmemo */ $creditmemo = $observer->getEvent()->getCreditmemo(); - $itemsToUpdate = []; - foreach ($creditmemo->getAllItems() as $item) { - $qty = $item->getQty(); - if (($item->getBackToStock() && $qty) || $this->stockConfiguration->isAutoReturnEnabled()) { - $productId = $item->getProductId(); - $parentItemId = $item->getOrderItem()->getParentItemId(); - /* @var $parentItem \Magento\Sales\Model\Order\Creditmemo\Item */ - $parentItem = $parentItemId ? $creditmemo->getItemByOrderId($parentItemId) : false; - $qty = $parentItem ? $parentItem->getQty() * $qty : $qty; - if (isset($itemsToUpdate[$productId])) { - $itemsToUpdate[$productId] += $qty; - } else { - $itemsToUpdate[$productId] = $qty; - } + $order = $this->orderRepository->get($creditmemo->getOrderId()); + $returnToStockItems = []; + foreach ($creditmemo->getItems() as $item) { + if ($item->getBackToStock()) { + $returnToStockItems[] = $item->getOrderItemId(); } } - if (!empty($itemsToUpdate)) { - $this->stockManagement->revertProductsSale( - $itemsToUpdate, - $creditmemo->getStore()->getWebsiteId() - ); - - $updatedItemIds = array_keys($itemsToUpdate); - $this->stockIndexerProcessor->reindexList($updatedItemIds); - $this->priceIndexer->reindexList($updatedItemIds); - } + $this->returnProcessor->execute( + $creditmemo, + $order, + $returnToStockItems, + $this->stockConfiguration->isAutoReturnEnabled() + ); } } diff --git a/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php b/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php index 523759d54645a..efa3bff32c0fa 100644 --- a/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php +++ b/app/code/Magento/SalesInventory/Test/Unit/Model/Order/ReturnProcessorTest.php @@ -5,9 +5,7 @@ */ namespace Magento\SalesInventory\Test\Unit\Model\Order; -use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\CatalogInventory\Api\StockManagementInterface; -use Magento\Sales\Api\CreditmemoRepositoryInterface; use Magento\Sales\Api\Data\CreditmemoInterface; use Magento\Sales\Api\Data\CreditmemoItemInterface; use Magento\Sales\Api\Data\OrderInterface; @@ -49,21 +47,11 @@ class ReturnProcessorTest extends \PHPUnit_Framework_TestCase */ private $priceIndexerMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|CreditmemoRepositoryInterface - */ - private $creditmemoRepositoryMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject|StoreManagerInterface */ private $storeManagerMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject|OrderRepositoryInterface - */ - private $orderRepositoryMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject|OrderItemRepositoryInterface */ @@ -95,13 +83,10 @@ public function setUp() $this->priceIndexerMock = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Price\Processor::class) ->disableOriginalConstructor() ->getMock(); - $this->creditmemoRepositoryMock = $this->getMockBuilder(CreditmemoRepositoryInterface::class) - ->disableOriginalConstructor() - ->getMock(); $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class) ->disableOriginalConstructor() ->getMock(); - $this->orderRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class) + $this->orderItemRepositoryMock = $this->getMockBuilder(OrderRepositoryInterface::class) ->disableOriginalConstructor() ->getMock(); $this->orderItemRepositoryMock = $this->getMockBuilder(OrderItemRepositoryInterface::class) @@ -127,9 +112,7 @@ public function setUp() $this->stockManagementMock, $this->stockIndexerProcessorMock, $this->priceIndexerMock, - $this->creditmemoRepositoryMock, $this->storeManagerMock, - $this->orderRepositoryMock, $this->orderItemRepositoryMock ); } @@ -139,6 +122,7 @@ public function testExecute() $orderItemId = 99; $productId = 50; $returnToStockItems = [$orderItemId]; + $parentItemId = 52; $qty = 1; $storeId = 0; $webSiteId = 10; @@ -147,10 +131,6 @@ public function testExecute() ->method('getItems') ->willReturn([$this->creditmemoItemMock]); - $this->creditmemoItemMock->expects($this->once()) - ->method('getQty') - ->willReturn($qty); - $this->creditmemoItemMock->expects($this->exactly(2)) ->method('getOrderItemId') ->willReturn($orderItemId); @@ -190,6 +170,14 @@ public function testExecute() ->method('reindexList') ->with([$productId]); + $this->orderItemMock->expects($this->once()) + ->method('getParentItemId') + ->willReturn($parentItemId); + + $this->creditmemoItemMock->expects($this->once()) + ->method('getQty') + ->willReturn($qty); + $this->returnProcessor->execute($this->creditmemoMock, $this->orderMock, $returnToStockItems); } } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php b/app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php similarity index 62% rename from app/code/Magento/CatalogInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php rename to app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php index f230e75cb385c..f4a9ca5eefdc1 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php +++ b/app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php @@ -3,9 +3,12 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\CatalogInventory\Test\Unit\Observer; +namespace Magento\SalesInventory\Test\Unit\Observer; -use Magento\CatalogInventory\Observer\RefundOrderInventoryObserver; +use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Model\OrderRepository; +use Magento\SalesInventory\Model\Order\ReturnProcessor; +use Magento\SalesInventory\Observer\RefundOrderInventoryObserver; class RefundOrderInventoryObserverTest extends \PHPUnit_Framework_TestCase { @@ -44,6 +47,26 @@ class RefundOrderInventoryObserverTest extends \PHPUnit_Framework_TestCase */ protected $eventObserver; + /** + * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager + */ + protected $objectManagerHelper; + + /** + * @var OrderRepository|\PHPUnit_Framework_MockObject_MockObject + */ + protected $orderRepositoryMock; + + /** + * @var ReturnProcessor|\PHPUnit_Framework_MockObject_MockObject + */ + protected $returnProcessorMock; + + /** + * @var OrderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $orderMock; + protected function setUp() { $this->stockIndexerProcessor = $this->getMock( @@ -90,8 +113,27 @@ protected function setUp() ->method('getEvent') ->will($this->returnValue($this->event)); +<<<<<<< HEAD $this->observer = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( 'Magento\CatalogInventory\Observer\RefundOrderInventoryObserver', +======= + $this->orderRepositoryMock = $this->getMockBuilder(OrderRepository::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->returnProcessorMock = $this->getMockBuilder(ReturnProcessor::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->orderMock = $this->getMockBuilder(OrderInterface::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->observer = $this->objectManagerHelper->getObject( + \Magento\SalesInventory\Observer\RefundOrderInventoryObserver::class, +>>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product [ 'stockConfiguration' => $this->stockConfiguration, 'stockManagement' => $this->stockManagement, @@ -99,15 +141,26 @@ protected function setUp() 'priceIndexer' => $this->priceIndexer, ] ); + + $this->objectManagerHelper->setBackwardCompatibleProperty( + $this->observer, + 'orderRepository', + $this->orderRepositoryMock + ); + $this->objectManagerHelper->setBackwardCompatibleProperty( + $this->observer, + 'returnProcessor', + $this->returnProcessorMock + ); } public function testRefundOrderInventory() { - $websiteId = 0; $ids = ['1', '14']; $items = []; $isAutoReturnEnabled = true; +<<<<<<< HEAD $store = $this->getMock( 'Magento\Store\Model\Store', ['getWebsiteId'], @@ -116,60 +169,66 @@ public function testRefundOrderInventory() false ); $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId)); +======= + $creditMemo = $this->getMock(\Magento\Sales\Model\Order\Creditmemo::class, [], [], '', false); +>>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product - $itemsToUpdate = []; foreach ($ids as $id) { $item = $this->getCreditMemoItem($id); $items[] = $item; - $itemsToUpdate[$item->getProductId()] = $item->getQty(); } +<<<<<<< HEAD $creditMemo = $this->getMock('Magento\Sales\Model\Order\Creditmemo', [], [], '', false); +======= + +>>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product $creditMemo->expects($this->once()) - ->method('getAllItems') + ->method('getItems') ->will($this->returnValue($items)); - $creditMemo->expects($this->once())->method('getStore')->will($this->returnValue($store)); $this->stockConfiguration->expects($this->any()) ->method('isAutoReturnEnabled') ->will($this->returnValue($isAutoReturnEnabled)); - $this->stockManagement->expects($this->once()) - ->method('revertProductsSale') - ->with($itemsToUpdate, $websiteId); - - $this->stockIndexerProcessor->expects($this->once()) - ->method('reindexList') - ->with($ids); - - $this->priceIndexer->expects($this->once()) - ->method('reindexList') - ->with($ids); - $this->event->expects($this->once()) ->method('getCreditmemo') ->will($this->returnValue($creditMemo)); + $this->orderRepositoryMock->expects($this->once()) + ->method('get') + ->willReturn($this->orderMock); + + $this->returnProcessorMock->expects($this->once()) + ->method('execute') + ->with($creditMemo, $this->orderMock, $ids, $isAutoReturnEnabled); + $this->observer->execute($this->eventObserver); } private function getCreditMemoItem($productId) { - $parentItemId = false; $backToStock = true; - $qty = 1; $item = $this->getMock( +<<<<<<< HEAD 'Magento\Sales\Model\Order\Creditmemo\Item', ['getProductId', 'getOrderItem', 'getBackToStock', 'getQty', '__wakeup'], +======= + \Magento\Sales\Model\Order\Creditmemo\Item::class, + ['getOrderItemId', 'getBackToStock', 'getQty', '__wakeup'], +>>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product [], '', false ); +<<<<<<< HEAD $orderItem = $this->getMock('Magento\Sales\Model\Order\Item', ['getParentItemId', '__wakeup'], [], '', false); $orderItem->expects($this->any())->method('getParentItemId')->willReturn($parentItemId); $item->expects($this->any())->method('getOrderItem')->willReturn($orderItem); $item->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); +======= +>>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product $item->expects($this->any())->method('getBackToStock')->willReturn($backToStock); - $item->expects($this->any())->method('getQty')->willReturn($qty); + $item->expects($this->any())->method('getOrderItemId')->willReturn($productId); return $item; } } diff --git a/app/code/Magento/SalesInventory/etc/events.xml b/app/code/Magento/SalesInventory/etc/events.xml new file mode 100644 index 0000000000000..a71ed7f8a28a1 --- /dev/null +++ b/app/code/Magento/SalesInventory/etc/events.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php new file mode 100644 index 0000000000000..e5c3ab4dad9ee --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php @@ -0,0 +1,118 @@ +fixtureFactory = $fixtureFactory; + parent::__construct($objectManager, $eventManager); + } + + /** + * Assert form data equals fixture data + * + * @param OrderInjectable $order + * @param array $data + * @param CatalogProductIndex $productGrid + * @param CatalogProductEdit $productPage + * @return void + */ + public function processAssert( + OrderInjectable $order, + array $data, + CatalogProductIndex $productGrid, + CatalogProductEdit $productPage + ) { + $product = $this->getProduct($order, $data); + $this->objectManager->get(\Magento\Catalog\Test\Constraint\AssertProductForm::class)->processAssert( + $product, + $productGrid, + $productPage + ); + } + + /** + * Get product's fixture. + * + * @param OrderInjectable $order + * @param array $data + * @param int $index [optional] + * @return FixtureInterface + */ + protected function getProduct(OrderInjectable $order, array $data, $index = 0) + { + if (!isset($data['items_data'][$index]['back_to_stock']) + || $data['items_data'][$index]['back_to_stock'] != 'Yes' + ) { + return $order->getEntityId()['products'][$index]; + } + $product = $order->getEntityId()['products'][$index]; + $productData = $product->getData(); + $checkoutDataQty = $productData['checkout_data']['qty']; + + $productKey = ''; + foreach ($productData['checkout_data']['options']['configurable_options'] as $option) { + $productKey .= ' ' . $option['title'] . ':' . $option['value']; + } + $productKey = trim($productKey); + $optionProduct = $productData['configurable_attributes_data']['matrix'][$productKey]; + $optionProduct['qty'] -= ($checkoutDataQty - $data['items_data'][$index]['qty']); + $productData = $optionProduct; + + $productData = array_diff_key($productData, array_flip($this->skipFields)); + + return $this->fixtureFactory->create(get_class($product), ['data' => $productData]); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Product qty was decreased after creditmemo creation.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml index c5b033caa7b05..ad77997ff21dc 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Repository/ConfigurableProduct.xml @@ -40,7 +40,40 @@ - Test configurable product %isolation% + sku_test_configurable_product_%isolation% + sku_test_configurable_product_%isolation% + + price_40 + + This item has weight + 30 + Yes + Catalog, Search + + taxable_goods + + configurable-product-%isolation% + + default + + + In Stock + + + + default + + + + default + + + configurable_options_with_qty_1 + + + + + sku_test_configurable_product_%isolation% sku_test_configurable_product_%isolation% 40 diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml new file mode 100644 index 0000000000000..dd92edc82b331 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml @@ -0,0 +1,21 @@ + + + + + + Assert items return to stock (partial refund) + Yes + 1 + default + configurableProduct::configurable_with_qty_1 + full_refund + + + + + diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php new file mode 100644 index 0000000000000..f48e9e198210c --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php @@ -0,0 +1,110 @@ +fixtureFactory = $fixtureFactory; + parent::__construct($objectManager, $eventManager); + } + + /** + * Assert form data equals fixture data + * + * @param OrderInjectable $order + * @param array $data + * @param CatalogProductIndex $productGrid + * @param CatalogProductEdit $productPage + * @return void + */ + public function processAssert( + OrderInjectable $order, + array $data, + CatalogProductIndex $productGrid, + CatalogProductEdit $productPage + ) { + $product = $this->getProduct($order, $data); + $this->objectManager->get(\Magento\Catalog\Test\Constraint\AssertProductForm::class)->processAssert( + $product, + $productGrid, + $productPage + ); + } + + /** + * Get product's fixture. + * + * @param OrderInjectable $order + * @param array $data + * @param int $index [optional] + * @return FixtureInterface + */ + protected function getProduct(OrderInjectable $order, array $data, $index = 0) + { + if (!isset($data['items_data'][$index]['back_to_stock']) + || $data['items_data'][$index]['back_to_stock'] != 'Yes' + ) { + return $order->getEntityId()['products'][$index]; + } + $product = $order->getEntityId()['products'][$index]; + $productData = $product->getData(); + $checkoutDataQty = $productData['checkout_data']['qty']; + $productData['quantity_and_stock_status']['qty'] -= ($checkoutDataQty - $data['items_data'][$index]['qty']); + + $productData = array_diff_key($productData, array_flip($this->skipFields)); + + return $this->fixtureFactory->create(get_class($product), ['data' => $productData]); + } + + /** + * Returns a string representation of the object. + * + * @return string + */ + public function toString() + { + return 'Product qty was decreased after creditmemo creation.'; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php index 36c9972bc9842..ba782d072b5e5 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.php @@ -94,32 +94,7 @@ public function test(OrderInjectable $order, array $data) return [ 'ids' => ['creditMemoIds' => $result['creditMemoIds']], - 'product' => $this->getProduct($order, $data), 'customer' => $order->getDataFieldConfig('customer_id')['source']->getCustomer() ]; } - - /** - * Get product's fixture. - * - * @param OrderInjectable $order - * @param array $data - * @param int $index [optional] - * @return FixtureInterface - */ - protected function getProduct(OrderInjectable $order, array $data, $index = 0) - { - if (!isset($data['items_data'][$index]['back_to_stock']) - || $data['items_data'][$index]['back_to_stock'] != 'Yes' - ) { - return $order->getEntityId()['products'][$index]; - } - $product = $order->getEntityId()['products'][$index]; - $productData = $product->getData(); - $checkoutDataQty = $productData['checkout_data']['qty']; - $productData['quantity_and_stock_status']['qty'] -= ($checkoutDataQty - $data['items_data'][$index]['qty']); - $productData = array_diff_key($productData, array_flip($this->skipFields)); - - return $this->fixtureFactory->create(get_class($product), ['data' => $productData]); - } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml index 40f5c0aefc60a..907e61b541b8a 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/CreateCreditMemoEntityTest.xml @@ -19,7 +19,7 @@ - + From 25c3c57df6f1327b9388ee620576cf2cff2fdab9 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Fri, 25 Nov 2016 12:37:42 +0200 Subject: [PATCH 04/43] MAGETWO-61232: Shipping rates can not be loaded --- .../Model/Address/AbstractAddress.php | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index 3ff2df1437ea4..fe391663c750a 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -263,7 +263,7 @@ public function setData($key, $value = null) { if (is_array($key)) { $key = $this->_implodeArrayField($key); - } elseif (is_array($value) && !empty($value) && $this->isAddressMultilineAttribute($key)) { + } elseif (is_array($value) && $this->isAddressMultilineAttribute($key)) { $value = $this->_implodeArrayValues($value); } return parent::setData($key, $value); @@ -291,7 +291,7 @@ protected function isAddressMultilineAttribute($code) protected function _implodeArrayField(array $data) { foreach ($data as $key => $value) { - if (is_array($value) && !empty($value) && $this->isAddressMultilineAttribute($key)) { + if (is_array($value) && $this->isAddressMultilineAttribute($key)) { $data[$key] = $this->_implodeArrayValues($data[$key]); } } @@ -301,22 +301,22 @@ protected function _implodeArrayField(array $data) /** * Combine values of field lines into a single string * - * @param string[]|string $value + * @param array $value * @return string */ - protected function _implodeArrayValues($value) + protected function _implodeArrayValues(array $value) { - if (is_array($value) && count($value)) { - $isScalar = false; - foreach ($value as $val) { - if (is_scalar($val)) { - $isScalar = true; - } - } - if ($isScalar) { - $value = trim(implode("\n", $value)); + $isScalar = true; + foreach ($value as $val) { + if (!is_scalar($val)) { + $isScalar = false; } } + + if ($isScalar) { + $value = trim(implode("\n", $value)); + } + return $value; } From 02b3a945eb951cdab7dbf3887416923d5aa0ddd8 Mon Sep 17 00:00:00 2001 From: Sergii Kovalenko Date: Fri, 25 Nov 2016 13:55:52 +0200 Subject: [PATCH 05/43] MAGETWO-61232: Shipping rates can not be loaded --- .../Customer/Model/Address/AbstractAddress.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Customer/Model/Address/AbstractAddress.php b/app/code/Magento/Customer/Model/Address/AbstractAddress.php index fe391663c750a..86f2f48ab0346 100644 --- a/app/code/Magento/Customer/Model/Address/AbstractAddress.php +++ b/app/code/Magento/Customer/Model/Address/AbstractAddress.php @@ -304,17 +304,19 @@ protected function _implodeArrayField(array $data) * @param array $value * @return string */ - protected function _implodeArrayValues(array $value) + protected function _implodeArrayValues($value) { - $isScalar = true; - foreach ($value as $val) { - if (!is_scalar($val)) { - $isScalar = false; + if (is_array($value)) { + $isScalar = true; + foreach ($value as $val) { + if (!is_scalar($val)) { + $isScalar = false; + } } - } - if ($isScalar) { - $value = trim(implode("\n", $value)); + if ($isScalar) { + $value = trim(implode("\n", $value)); + } } return $value; From 9112b4c47a88850c0ec03edc223aa8d6fc335f47 Mon Sep 17 00:00:00 2001 From: Olga Nakonechna Date: Fri, 25 Nov 2016 15:25:47 +0200 Subject: [PATCH 06/43] MAGETWO-61268: [Backport] - Creditmemo return to stock only one unit of configurable product - for 2.0.11 --- .../RefundOrderInventoryObserverTest.php | 49 ++++--------------- 1 file changed, 10 insertions(+), 39 deletions(-) diff --git a/app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php b/app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php index f4a9ca5eefdc1..95b2067a759df 100644 --- a/app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php +++ b/app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php @@ -10,6 +10,9 @@ use Magento\SalesInventory\Model\Order\ReturnProcessor; use Magento\SalesInventory\Observer\RefundOrderInventoryObserver; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class RefundOrderInventoryObserverTest extends \PHPUnit_Framework_TestCase { /** @@ -70,7 +73,7 @@ class RefundOrderInventoryObserverTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->stockIndexerProcessor = $this->getMock( - 'Magento\CatalogInventory\Model\Indexer\Stock\Processor', + \Magento\CatalogInventory\Model\Indexer\Stock\Processor::class, ['reindexList'], [], '', @@ -78,7 +81,7 @@ protected function setUp() ); $this->stockManagement = $this->getMock( - 'Magento\CatalogInventory\Model\StockManagement', + \Magento\CatalogInventory\Model\StockManagement::class, [], [], '', @@ -86,7 +89,7 @@ protected function setUp() ); $this->stockConfiguration = $this->getMockForAbstractClass( - 'Magento\CatalogInventory\Api\StockConfigurationInterface', + \Magento\CatalogInventory\Api\StockConfigurationInterface::class, [ 'isAutoReturnEnabled', 'isDisplayProductStockStatus' @@ -95,16 +98,16 @@ protected function setUp() false ); - $this->priceIndexer = $this->getMockBuilder('Magento\Catalog\Model\Indexer\Product\Price\Processor') + $this->priceIndexer = $this->getMockBuilder(\Magento\Catalog\Model\Indexer\Product\Price\Processor::class) ->disableOriginalConstructor() ->getMock(); - $this->event = $this->getMockBuilder('Magento\Framework\Event') + $this->event = $this->getMockBuilder(\Magento\Framework\Event::class) ->disableOriginalConstructor() ->setMethods(['getProduct', 'getCollection', 'getCreditmemo', 'getQuote', 'getWebsite']) ->getMock(); - $this->eventObserver = $this->getMockBuilder('Magento\Framework\Event\Observer') + $this->eventObserver = $this->getMockBuilder(\Magento\Framework\Event\Observer::class) ->disableOriginalConstructor() ->setMethods(['getEvent']) ->getMock(); @@ -113,10 +116,6 @@ protected function setUp() ->method('getEvent') ->will($this->returnValue($this->event)); -<<<<<<< HEAD - $this->observer = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject( - 'Magento\CatalogInventory\Observer\RefundOrderInventoryObserver', -======= $this->orderRepositoryMock = $this->getMockBuilder(OrderRepository::class) ->disableOriginalConstructor() ->getMock(); @@ -133,7 +132,6 @@ protected function setUp() $this->observer = $this->objectManagerHelper->getObject( \Magento\SalesInventory\Observer\RefundOrderInventoryObserver::class, ->>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product [ 'stockConfiguration' => $this->stockConfiguration, 'stockManagement' => $this->stockManagement, @@ -160,28 +158,13 @@ public function testRefundOrderInventory() $items = []; $isAutoReturnEnabled = true; -<<<<<<< HEAD - $store = $this->getMock( - 'Magento\Store\Model\Store', - ['getWebsiteId'], - [], - '', - false - ); - $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId)); -======= $creditMemo = $this->getMock(\Magento\Sales\Model\Order\Creditmemo::class, [], [], '', false); ->>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product foreach ($ids as $id) { $item = $this->getCreditMemoItem($id); $items[] = $item; } -<<<<<<< HEAD - $creditMemo = $this->getMock('Magento\Sales\Model\Order\Creditmemo', [], [], '', false); -======= ->>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product $creditMemo->expects($this->once()) ->method('getItems') ->will($this->returnValue($items)); @@ -209,26 +192,14 @@ private function getCreditMemoItem($productId) { $backToStock = true; $item = $this->getMock( -<<<<<<< HEAD - 'Magento\Sales\Model\Order\Creditmemo\Item', - ['getProductId', 'getOrderItem', 'getBackToStock', 'getQty', '__wakeup'], -======= \Magento\Sales\Model\Order\Creditmemo\Item::class, ['getOrderItemId', 'getBackToStock', 'getQty', '__wakeup'], ->>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product [], '', false ); -<<<<<<< HEAD - $orderItem = $this->getMock('Magento\Sales\Model\Order\Item', ['getParentItemId', '__wakeup'], [], '', false); - $orderItem->expects($this->any())->method('getParentItemId')->willReturn($parentItemId); - $item->expects($this->any())->method('getOrderItem')->willReturn($orderItem); - $item->expects($this->any())->method('getProductId')->will($this->returnValue($productId)); -======= ->>>>>>> e0d9191... MAGETWO-59074: Creditmemo return to stock only one unit of configurable product $item->expects($this->any())->method('getBackToStock')->willReturn($backToStock); $item->expects($this->any())->method('getOrderItemId')->willReturn($productId); return $item; } -} +} \ No newline at end of file From 085b974e759b62fbaedd05284ea34dbb2fe43226 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Thu, 24 Nov 2016 11:05:17 +0200 Subject: [PATCH 07/43] MAGETWO-61106: Configurable product page does not display swatches --- .../view/frontend/templates/product/layered/renderer.phtml | 2 +- .../view/frontend/templates/product/listing/renderer.phtml | 2 +- .../view/frontend/templates/product/view/renderer.phtml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml index 78c1b50da9fa3..9067552b7f23b 100644 --- a/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml +++ b/app/code/Magento/Swatches/view/frontend/templates/product/layered/renderer.phtml @@ -69,7 +69,7 @@