diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php
index 4375092591d194962b108e2ba0351b1a03fa7e5c..40516e55e930c4021699dad26b43a4e83fe26a80 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/FlatTableBuilder.php
@@ -281,7 +281,7 @@ class FlatTableBuilder
             if (!empty($columnValueNames)) {
                 $select->joinLeft(
                     $temporaryValueTableName,
-                    sprintf('e.%1$s = %2$s.%1$s', $linkField, $temporaryTableName),
+                    sprintf('e.%1$s = %2$s.%1$s', $linkField, $temporaryValueTableName),
                     $columnValueNames
                 );
                 $allColumns = array_merge($allColumns, $columnValueNames);
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/FlatTableBuilderTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/FlatTableBuilderTest.php
index 7e5a8305467e8e979a9ccc79d39d7ffdb70bb339..d90261f068f5023d8987bab6d64585032385c8ee 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/FlatTableBuilderTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/FlatTableBuilderTest.php
@@ -107,44 +107,42 @@ class FlatTableBuilderTest extends \PHPUnit_Framework_TestCase
 
     public function testBuild()
     {
-        list($storeId, $changedIds, $valueFieldSuffix, $tableDropSuffix, $fillTmpTables) = [1, [], '', '', true];
+        $storeId = 1;
+        $changedIds = [];
+        $valueFieldSuffix = '_value';
+        $tableDropSuffix = '';
+        $fillTmpTables = true;
         $tableName = 'catalog_product_entity';
         $attributeTable = 'catalog_product_entity_int';
         $temporaryTableName = 'catalog_product_entity_int_tmp_indexer';
-        $temporaryValueTableName = 'catalog_product_entity_int_tmp_indexer';
+        $temporaryValueTableName = 'catalog_product_entity_int_tmp_indexer_value';
         $linkField = 'entity_id';
         $statusId = 22;
+        $eavCustomField = 'space_weight';
+        $eavCustomValueField = $eavCustomField . $valueFieldSuffix;
         $this->flatIndexerMock->expects($this->once())->method('getAttributes')->willReturn([]);
         $this->flatIndexerMock->expects($this->exactly(3))->method('getFlatColumns')
-            ->willReturnOnConsecutiveCalls(
-                [],
-                [$linkField => []],
-                [$linkField => []]
-            );
+            ->willReturnOnConsecutiveCalls([], [$eavCustomValueField => []], [$eavCustomValueField => []]);
         $this->flatIndexerMock->expects($this->once())->method('getFlatIndexes')->willReturn([]);
         $statusAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute::class)
             ->disableOriginalConstructor()
             ->getMock();
+        $eavCustomAttributeMock = $this->getMockBuilder(\Magento\Eav\Model\Entity\Attribute::class)
+            ->disableOriginalConstructor()
+            ->getMock();
         $this->flatIndexerMock->expects($this->once())->method('getTablesStructure')
             ->willReturn(
                 [
-                    'catalog_product_entity' => [
-                        $linkField => $statusAttributeMock
-                    ],
+                    'catalog_product_entity' => [$linkField => $statusAttributeMock],
                     'catalog_product_entity_int' => [
-                        $linkField => $statusAttributeMock
+                        $linkField => $statusAttributeMock,
+                        $eavCustomField => $eavCustomAttributeMock
                     ]
                 ]
             );
         $this->flatIndexerMock->expects($this->atLeastOnce())->method('getTable')
-            ->withConsecutive(
-                [$tableName],
-                ['catalog_product_website']
-            )
-            ->willReturnOnConsecutiveCalls(
-                $tableName,
-                'catalog_product_website'
-            );
+            ->withConsecutive([$tableName], ['catalog_product_website'])
+            ->willReturnOnConsecutiveCalls($tableName, 'catalog_product_website');
         $this->flatIndexerMock->expects($this->once())->method('getAttribute')
             ->with('status')
             ->willReturn($statusAttributeMock);
@@ -155,6 +153,9 @@ class FlatTableBuilderTest extends \PHPUnit_Framework_TestCase
         $statusAttributeMock->expects($this->atLeastOnce())->method('getBackend')->willReturn(
             $backendMock
         );
+        $eavCustomAttributeMock->expects($this->atLeastOnce())->method('getBackend')->willReturn(
+            $backendMock
+        );
         $statusAttributeMock->expects($this->atLeastOnce())->method('getId')->willReturn($statusId);
         $tableMock = $this->getMockBuilder(\Magento\Framework\DB\Ddl\Table::class)
             ->disableOriginalConstructor()
@@ -185,12 +186,12 @@ class FlatTableBuilderTest extends \PHPUnit_Framework_TestCase
                 [
                     $temporaryTableName,
                     "e.{$linkField} = {$temporaryTableName}.{$linkField}",
-                    [$linkField]
+                    [$linkField, $eavCustomField]
                 ],
                 [
                     $temporaryValueTableName,
-                    "e.{$linkField} = " . $temporaryValueTableName . ".{$linkField}",
-                    [$linkField]
+                    "e.{$linkField} = {$temporaryValueTableName}.{$linkField}",
+                    [$eavCustomValueField]
                 ]
             )->willReturnSelf();
         $this->metadataPoolMock->expects($this->atLeastOnce())->method('getMetadata')->with(ProductInterface::class)
diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ImagesTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ImagesTest.php
index 2172e184a9a2ed400d80eb89314855c69fb2c7c1..7a55bd31e3deef64ddeaf5b452cc1b7eb389517c 100644
--- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ImagesTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/ImagesTest.php
@@ -24,7 +24,9 @@ class ImagesTest extends AbstractModifierTest
 
     public function testModifyData()
     {
-        $this->assertSame($this->getSampleData(), $this->getModel()->modifyData($this->getSampleData()));
+        $this->productMock->expects($this->once())->method('getId')->willReturn(2051);
+        $actualResult = $this->getModel()->modifyData($this->getSampleData());
+        $this->assertSame("", $actualResult[2051]['product']['media_gallery']['images'][0]['label']);
     }
 
     public function testModifyMeta()
@@ -40,4 +42,24 @@ class ImagesTest extends AbstractModifierTest
 
         $this->assertSame([], $this->getModel()->modifyMeta($meta));
     }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function getSampleData()
+    {
+        return [
+            2051 => [
+                'product' => [
+                    'media_gallery' => [
+                        'images' => [
+                            [
+                                'label' => null
+                            ]
+                        ]
+                    ]
+                ]
+            ]
+        ];
+    }
 }
diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php
index 810a06df4a42f76392ee54525eb5bf6ffc5f489f..a8536cacc79668797ac961e1082c7b8c0f020e76 100644
--- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php
+++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Images.php
@@ -51,6 +51,21 @@ class Images extends AbstractModifier
      */
     public function modifyData(array $data)
     {
+        /** @var \Magento\Catalog\Api\Data\ProductInterface $product */
+        $product = $this->locator->getProduct();
+        $modelId = $product->getId();
+        if (
+            isset($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery'])
+            && !empty($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery'])
+            && !empty($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images'])
+        ) {
+            foreach ($data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images'] as $index => $image) {
+                if (!isset($image['label'])) {
+                    $data[$modelId][self::DATA_SOURCE_DEFAULT]['media_gallery']['images'][$index]['label'] = "";
+                }
+            }
+        };
+
         return $data;
     }
 }
diff --git a/app/code/Magento/CatalogInventory/etc/events.xml b/app/code/Magento/CatalogInventory/etc/events.xml
index a1476c2c3f8b161568a042725d6b04c37aeb1be9..d9db59b7a17663b48b2ba2df7677d4147cba11b5 100644
--- a/app/code/Magento/CatalogInventory/etc/events.xml
+++ b/app/code/Magento/CatalogInventory/etc/events.xml
@@ -33,9 +33,6 @@
     <event name="sales_order_item_cancel">
         <observer name="inventory" instance="Magento\CatalogInventory\Observer\CancelOrderItemObserver"/>
     </event>
-    <event name="sales_order_creditmemo_save_after">
-        <observer name="inventory" instance="Magento\CatalogInventory\Observer\RefundOrderInventoryObserver"/>
-    </event>
     <event name="catalog_product_save_after">
         <observer name="inventory" instance="Magento\CatalogInventory\Observer\SaveInventoryDataObserver"/>
     </event>
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js b/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js
index e06b8922b2252fd497db66a79db35af8c543db09..eba77927be79ea6189884f412be03be7ec7a76be 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/region-updater.js
@@ -7,9 +7,10 @@
 define([
     'jquery',
     'mage/template',
+    'underscore',
     'jquery/ui',
     'mage/validation'
-], function ($, mageTemplate) {
+], function ($, mageTemplate, _) {
     'use strict';
 
     $.widget('mage.regionUpdater', {
@@ -124,6 +125,8 @@ define([
          * @private
          */
         _clearError: function () {
+            var args = ['clearError', this.options.regionListId, this.options.regionInputId, this.options.postcodeId];
+
             if (this.options.clearError && typeof this.options.clearError === 'function') {
                 this.options.clearError.call(this);
             } else {
@@ -133,8 +136,8 @@ define([
 
                 this.options.form = $(this.options.form);
 
-                this.options.form && this.options.form.data('validator') && this.options.form.validation('clearError',
-                    this.options.regionListId, this.options.regionInputId, this.options.postcodeId);
+                this.options.form && this.options.form.data('validator') &&
+                    this.options.form.validation.apply(this.options.form, _.compact(args));
 
                 // Clean up errors on region & zip fix
                 $(this.options.regionInputId).removeClass('mage-error').parent().find('[generated]').remove();
diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php
index 36f1310079ed534d928fa03be511a64265f71dc5..ac3ffdc3d622c956074b3fc174df6c24e4cabff3 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 @@ class CreditmemoLoader extends DataObject
             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 21104933a51d6d8fda5d225ff4b879a07def3d20..ff687074e4a66cc50c457c685fc1757d1529dcb6 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 @@ class CreditmemoFactory
 
             $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 @@ class CreditmemoFactory
 
             $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 @@ class CreditmemoFactory
             $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/Sales/view/adminhtml/layout/sales_order_create_index.xml b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml
index b2e779e330fe0582f855f17ee57e6f648f61a001..6acb23ab0910ea3e8dc1e8bd5e87c28900e19da5 100644
--- a/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml
+++ b/app/code/Magento/Sales/view/adminhtml/layout/sales_order_create_index.xml
@@ -16,7 +16,7 @@
 
         <referenceBlock name="page.title">
             <action method="setTitleId">
-                <argument translate="true" name="id" xsi:type="string">order-header</argument>
+                <argument translate="false" name="id" xsi:type="string">order-header</argument>
             </action>
         </referenceBlock>
         <referenceContainer name="after.body.start">
diff --git a/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml b/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml
index 59bb31a94fa0cadadf177f695271c1efeaa69aa6..a8ccf82c5fe06030055381d9c13228661308e04e 100644
--- a/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml
+++ b/app/code/Magento/Sales/view/adminhtml/templates/order/create/sidebar/items.phtml
@@ -66,7 +66,13 @@
                         <?php endif; ?>
 
                         <?php if ($block->canDisplayPrice()): ?>
-                            <td class="col-price"><?php /* @noEscape */ echo $block->getItemPrice($_item) ?></td>
+                            <td class="col-price">
+                                <?php if ($block->getDataId() == 'cart'): ?>
+                                    <?php /* @noEscape */ echo $block->getItemPrice($_item->getProduct()) ?>
+                                <?php else: ?>
+                                    <?php /* @noEscape */ echo $block->getItemPrice($_item) ?>
+                                <?php endif; ?>
+                            </td>
                         <?php endif; ?>
 
                         <?php if ($block->canRemoveItems()): ?>
diff --git a/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php b/app/code/Magento/SalesInventory/Model/Order/ReturnProcessor.php
index 7752d7131031cf0daa63f4c8b8bf49609e3090ed..3680bbb3a1eaefa3ee822eefd99b7b21b320a3f8 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 @@ class ReturnProcessor
      * @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 @@ class ReturnProcessor
         }
     }
 
-    /**
-     * @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 9702bfc7cfe425b2c8987c1aec4e86430e1d62ac..acdebcf976a2eead77eb6074611968a9831cd524 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 @@ class RefundOrderInventoryObserver implements ObserverInterface
     {
         /* @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 523759d54645a1e2db471db948fa116cf59cd32e..efa3bff32c0fa2b40c3a9a57ec04cb1ec5c9f257 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 @@ class ReturnProcessorTest extends \PHPUnit_Framework_TestCase
         $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 @@ class ReturnProcessorTest extends \PHPUnit_Framework_TestCase
             $this->stockManagementMock,
             $this->stockIndexerProcessorMock,
             $this->priceIndexerMock,
-            $this->creditmemoRepositoryMock,
             $this->storeManagerMock,
-            $this->orderRepositoryMock,
             $this->orderItemRepositoryMock
         );
     }
@@ -139,6 +122,7 @@ class ReturnProcessorTest extends \PHPUnit_Framework_TestCase
         $orderItemId = 99;
         $productId = 50;
         $returnToStockItems = [$orderItemId];
+        $parentItemId = 52;
         $qty = 1;
         $storeId = 0;
         $webSiteId = 10;
@@ -147,10 +131,6 @@ class ReturnProcessorTest extends \PHPUnit_Framework_TestCase
             ->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 @@ class ReturnProcessorTest extends \PHPUnit_Framework_TestCase
             ->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 65%
rename from app/code/Magento/CatalogInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php
rename to app/code/Magento/SalesInventory/Test/Unit/Observer/RefundOrderInventoryObserverTest.php
index e440ed3380498a0c8d0deb9fb4edbd68a5d2c295..4e553493d07f63ed9f7d0a2d0d0ec7129d7580e7 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;
 
 /**
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -47,6 +50,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(
@@ -93,8 +116,22 @@ class RefundOrderInventoryObserverTest extends \PHPUnit_Framework_TestCase
             ->method('getEvent')
             ->will($this->returnValue($this->event));
 
-        $this->observer = (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject(
-            \Magento\CatalogInventory\Observer\RefundOrderInventoryObserver::class,
+        $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,
             [
                 'stockConfiguration' => $this->stockConfiguration,
                 'stockManagement' => $this->stockManagement,
@@ -102,83 +139,67 @@ class RefundOrderInventoryObserverTest extends \PHPUnit_Framework_TestCase
                 '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;
 
-        $store = $this->getMock(
-            \Magento\Store\Model\Store::class,
-            ['getWebsiteId'],
-            [],
-            '',
-            false
-        );
-        $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId));
+        $creditMemo = $this->getMock(\Magento\Sales\Model\Order\Creditmemo::class, [], [], '', false);
 
-        $itemsToUpdate = [];
         foreach ($ids as $id) {
             $item = $this->getCreditMemoItem($id);
             $items[] = $item;
-            $itemsToUpdate[$item->getProductId()] = $item->getQty();
         }
-        $creditMemo = $this->getMock(\Magento\Sales\Model\Order\Creditmemo::class, [], [], '', false);
+
         $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(
             \Magento\Sales\Model\Order\Creditmemo\Item::class,
-            ['getProductId', 'getOrderItem', 'getBackToStock', 'getQty', '__wakeup'],
-            [],
-            '',
-            false
-        );
-        $orderItem = $this->getMock(
-            \Magento\Sales\Model\Order\Item::class,
-            ['getParentItemId', '__wakeup'],
+            ['getOrderItemId', 'getBackToStock', 'getQty', '__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));
         $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 0000000000000000000000000000000000000000..a71ed7f8a28a16a4ded03e507876757ec94f436c
--- /dev/null
+++ b/app/code/Magento/SalesInventory/etc/events.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
+    <event name="sales_order_creditmemo_save_after">
+        <observer name="inventory" instance="Magento\SalesInventory\Observer\RefundOrderInventoryObserver"/>
+    </event>
+</config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/BlockGallery.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/BlockGallery.php
new file mode 100644
index 0000000000000000000000000000000000000000..bc0d0b87f24bba19d2e249fa37be7e59e16cca92
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/BlockGallery.php
@@ -0,0 +1,49 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section;
+
+use Magento\Mtf\Client\Element\SimpleElement;
+use Magento\Mtf\Client\Locator;
+use Magento\Ui\Test\Block\Adminhtml\Section;
+
+/**
+ * Class for product gallery block.
+ */
+class BlockGallery extends Section
+{
+    /**
+     * Selector for image loader container.
+     *
+     * @var string
+     */
+    private $imageLoader = '.image.image-placeholder .file-row';
+
+    /**
+     * Selector for image upload input.
+     *
+     * @var string
+     */
+    private $imageUploadInput = '[name="image"]';
+
+    /**
+     * Upload product images.
+     *
+     * @param array $data
+     * @param SimpleElement|null $element
+     * @return $this
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function setFieldsData(array $data, SimpleElement $element = null)
+    {
+        foreach ($data['image']['value'] as $imageData) {
+            $uploadElement = $element->find($this->imageUploadInput, Locator::SELECTOR_CSS, 'upload');
+            $uploadElement->setValue($imageData['file']);
+            $this->waitForElementNotVisible($this->imageLoader);
+        }
+        return $this;
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
index 407b5c9cb20a3b2097ea87e9d1f5a8240e5566b2..3b66164ebe658097e05fdba2e8b53c6cb3d643d2 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml
@@ -143,7 +143,7 @@
         </fields>
     </attributes>
     <gallery>
-        <class>\Magento\Ui\Test\Block\Adminhtml\Section</class>
+        <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\BlockGallery</class>
         <selector>[data-index='block_gallery']</selector>
         <strategy>css selector</strategy>
     </gallery>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCanSaveProduct.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCanSaveProduct.php
new file mode 100644
index 0000000000000000000000000000000000000000..04e1c034b3db77a49a583ee819f9b8d97cb440ba
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertCanSaveProduct.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+/**
+ * Assert that can save already exist product.
+ */
+class AssertCanSaveProduct extends \Magento\Mtf\Constraint\AbstractConstraint
+{
+    /**
+     * Assert that can save already existing product.
+     *
+     * @param \Magento\Mtf\Fixture\FixtureInterface $product
+     * @param \Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit $catalogProductEdit
+     * @param \Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex $catalogProductIndex
+     * @return void
+     */
+    public function processAssert(
+        \Magento\Mtf\Fixture\FixtureInterface $product,
+        \Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit $catalogProductEdit,
+        \Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex $catalogProductIndex
+    ) {
+        $filter = ['sku' => $product->getSku()];
+        $catalogProductIndex->open()->getProductGrid()->searchAndOpen($filter);
+        $catalogProductEdit->getFormPageActions()->save();
+
+        \PHPUnit_Framework_Assert::assertNotEmpty(
+            $catalogProductEdit->getMessagesBlock()->getSuccessMessage(),
+            'Can\'t save existing product.'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product was saved without errors.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductHasImageInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductHasImageInGrid.php
new file mode 100644
index 0000000000000000000000000000000000000000..fed3b36c08d661bbc0297b6f87d08aa692d3c04e
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductHasImageInGrid.php
@@ -0,0 +1,45 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Constraint;
+
+use Magento\Mtf\Fixture\InjectableFixture;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+
+class AssertProductHasImageInGrid extends AbstractConstraint
+{
+    /**
+     * Assert that product image is present in grid.
+     *
+     * @param CatalogProductIndex $productGrid
+     * @param InjectableFixture $product
+     * @return void
+     */
+    public function processAssert(
+        CatalogProductIndex $productGrid,
+        InjectableFixture $product
+    ) {
+        $filter = ['sku' => $product->getSku()];
+        $productGrid->open();
+        $productGrid->getProductGrid()->search($filter);
+        $src = $productGrid->getProductGrid()->getBaseImageSource();
+        \PHPUnit_Framework_Assert::assertTrue(
+            strpos($src, '/placeholder/') === false,
+            'Product image is not present in product grid when it should be'
+        );
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return string
+     */
+    public function toString()
+    {
+        return 'Product image is displayed in product grid.';
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
index b4514208a509358a6828a7b77d33ca0c2678072a..e8ceb1d0889247805746a401f6c60bb5a0556010 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml
@@ -36,8 +36,8 @@
         <field name="gallery" is_required="0" />
         <field name="gift_message_available" is_required="0" />
         <field name="has_options" is_required="0" />
-        <field name="image" is_required="0" />
-        <field name="image_label" is_required="0" />
+        <field name="image" is_required="0" group="gallery" source="Magento\Catalog\Test\Fixture\Product\Image" />
+        <field name="image_label" group="gallery" is_required="0" />
         <field name="manufacturer" is_required="0" />
         <field name="media_gallery" is_required="0" />
         <field name="meta_description" is_required="0" group="search-engine-optimization" />
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/Image.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/Image.php
new file mode 100644
index 0000000000000000000000000000000000000000..ad72a6db4f4cef615f4abb7edddc497886a73981
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/Product/Image.php
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Catalog\Test\Fixture\Product;
+
+use Magento\Mtf\Fixture\DataSource;
+use Magento\Mtf\Fixture\FixtureFactory;
+
+/**
+ * Image entity data source.
+ */
+class Image extends DataSource
+{
+    /**
+     * Fixture Factory instance.
+     *
+     * @var FixtureFactory
+     */
+    private $fixtureFactory;
+
+    /**
+     * Fixture data.
+     *
+     * @var array
+     */
+    private $fixtureData;
+
+    /**
+     * @param FixtureFactory $fixtureFactory
+     * @param array $params
+     * @param array $data
+     */
+    public function __construct(FixtureFactory $fixtureFactory, array $params, $data = [])
+    {
+        $this->fixtureFactory = $fixtureFactory;
+        $this->params = $params;
+        $this->fixtureData = $data;
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws \Exception
+     */
+    public function getData($key = null)
+    {
+        foreach ($this->fixtureData as &$imageData) {
+            if (isset($imageData['file']) && file_exists(MTF_TESTS_PATH . $imageData['file'])) {
+                $imageData['file'] = MTF_TESTS_PATH . $imageData['file'];
+            } else {
+                throw new \Exception("Image '{$imageData['file']}'' not found on the server.");
+            }
+        }
+        $this->data = $this->fixtureData;
+
+        return parent::getData($key);
+    }
+}
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml
index d9ef9f0b0420d6545718bae78b006417f7684b33..9f4a5e4bb71fea9293612125157757f7e3d965da 100644
--- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/CreateSimpleProductEntityTest.xml
@@ -509,5 +509,19 @@
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductPage" />
             <constraint name="Magento\Catalog\Test\Constraint\AssertProductInCart" />
         </variation>
+        <variation name="CreateSimpleProductEntityWithImageTestVariation1" summary="Create product with image and try to save it again">
+            <data name="product/data/image/0/file" xsi:type="string">Magento/Catalog/Test/_files/test1.png</data>
+            <data name="product/data/image/1/file" xsi:type="string">Magento/Catalog/Test/_files/test2.png</data>
+            <data name="product/data/url_key" xsi:type="string">simple-product-%isolation%</data>
+            <data name="product/data/name" xsi:type="string">Simple Product %isolation%</data>
+            <data name="product/data/sku" xsi:type="string">simple_sku_%isolation%</data>
+            <data name="product/data/price/value" xsi:type="string">10</data>
+            <data name="product/data/weight" xsi:type="string">50</data>
+            <data name="tag" xsi:type="string">severity:S1</data>
+            <data name="product/data/quantity_and_stock_status/qty" xsi:type="string">100</data>
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductSaveMessage" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertProductHasImageInGrid" />
+            <constraint name="Magento\Catalog\Test\Constraint\AssertCanSaveProduct" />
+        </variation>
     </testCase>
 </config>
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/_files/test1.png b/dev/tests/functional/tests/app/Magento/Catalog/Test/_files/test1.png
new file mode 100644
index 0000000000000000000000000000000000000000..3077df38da2ffab3378a630914803dfad59e7961
Binary files /dev/null and b/dev/tests/functional/tests/app/Magento/Catalog/Test/_files/test1.png differ
diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/_files/test2.png b/dev/tests/functional/tests/app/Magento/Catalog/Test/_files/test2.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d219e6ee734b983a39e041a2386117a10d762be
Binary files /dev/null and b/dev/tests/functional/tests/app/Magento/Catalog/Test/_files/test2.png differ
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 0000000000000000000000000000000000000000..e5c3ab4dad9ee121c1332649dabd8715c3544449
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php
@@ -0,0 +1,118 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\ConfigurableProduct\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\Mtf\ObjectManager;
+use Magento\Mtf\System\Event\EventManagerInterface;
+use Magento\Sales\Test\Fixture\OrderInjectable;
+
+/**
+ * Class AssertProductQtyDecreasedAfterCreditmemo
+ */
+class AssertProductQtyDecreasedAfterCreditmemo extends AbstractConstraint
+{
+    /**
+     * @var FixtureFactory
+     */
+    protected $fixtureFactory;
+
+    /**
+     * Skip fields for create product fixture.
+     *
+     * @var array
+     */
+    protected $skipFields = [
+        'attribute_set_id',
+        'website_ids',
+        'checkout_data',
+        'type_id',
+        'price',
+    ];
+
+    /**
+     * AssertFirstProductForm constructor.
+     * @param ObjectManager $objectManager
+     */
+    public function __construct(
+        ObjectManager $objectManager,
+        EventManagerInterface $eventManager,
+        FixtureFactory $fixtureFactory
+    ) {
+        $this->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 4a69a7604bca3d74119b07bdcea3b2115a1f6648..32f1957d4173f87b10069b60c8c428b921e260fb 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
@@ -71,7 +71,40 @@
         </dataset>
 
         <dataset name="configurable_with_qty_1">
-            <field name="name" xsi:type="string">Test configurable product %isolation%</field>
+            <field name="name" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
+            <field name="price" xsi:type="array">
+                <item name="dataset" xsi:type="string">price_40</item>
+            </field>
+            <field name="product_has_weight" xsi:type="string">This item has weight</field>
+            <field name="weight" xsi:type="string">30</field>
+            <field name="status" xsi:type="string">Yes</field>
+            <field name="visibility" xsi:type="string">Catalog, Search</field>
+            <field name="tax_class_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">taxable_goods</item>
+            </field>
+            <field name="url_key" xsi:type="string">configurable-product-%isolation%</field>
+            <field name="configurable_attributes_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="quantity_and_stock_status" xsi:type="array">
+                <item name="is_in_stock" xsi:type="string">In Stock</item>
+            </field>
+            <field name="website_ids" xsi:type="array">
+                <item name="0" xsi:type="array">
+                    <item name="dataset" xsi:type="string">default</item>
+                </item>
+            </field>
+            <field name="attribute_set_id" xsi:type="array">
+                <item name="dataset" xsi:type="string">default</item>
+            </field>
+            <field name="checkout_data" xsi:type="array">
+                <item name="dataset" xsi:type="string">configurable_options_with_qty_1</item>
+            </field>
+        </dataset>
+
+        <dataset name="configurable_with_qty_2">
+            <field name="name" xsi:type="string">sku_test_configurable_product_%isolation%</field>
             <field name="sku" xsi:type="string">sku_test_configurable_product_%isolation%</field>
             <field name="price" xsi:type="array">
                 <item name="dataset" xsi:type="string">price_40</item>
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 0000000000000000000000000000000000000000..dd92edc82b3310ad9610c70138578a220e4358cd
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateCreditMemoEntityTest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+ -->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/variations.xsd">
+    <testCase name="Magento\Sales\Test\TestCase\CreateCreditMemoEntityTest" summary="Create Credit Memo for Offline Payment Methods" ticketId="MAGETWO-59074">
+        <variation name="CreateCreditMemoEntityWithConfigurableTestVariation1" ticketId="MAGETWO-12447">
+            <data name="description" xsi:type="string">Assert items return to stock (partial refund)</data>
+            <data name="data/items_data/0/back_to_stock" xsi:type="string">Yes</data>
+            <data name="data/items_data/0/qty" xsi:type="string">1</data>
+            <data name="order/dataset" xsi:type="string">default</data>
+            <data name="order/data/entity_id/products" xsi:type="string">configurableProduct::configurable_with_qty_1</data>
+            <data name="order/data/price/dataset" xsi:type="string">full_refund</data>
+            <constraint name="Magento\Sales\Test\Constraint\AssertRefundSuccessCreateMessage" />
+            <constraint name="Magento\ConfigurableProduct\Test\Constraint\AssertProductQtyDecreasedAfterCreditmemo" />
+        </variation>
+    </testCase>
+</config>
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 0000000000000000000000000000000000000000..f48e9e198210c02a66870674cbc35178b7d91df4
--- /dev/null
+++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertProductQtyDecreasedAfterCreditmemo.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Sales\Test\Constraint;
+
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit;
+use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex;
+use Magento\Mtf\Constraint\AbstractConstraint;
+use Magento\Mtf\Fixture\FixtureFactory;
+use Magento\Mtf\Fixture\FixtureInterface;
+use Magento\Mtf\ObjectManager;
+use Magento\Mtf\System\Event\EventManagerInterface;
+use Magento\Sales\Test\Fixture\OrderInjectable;
+
+/**
+ * Class AssertProductQtyDecreasedAfterCreditmemo
+ */
+class AssertProductQtyDecreasedAfterCreditmemo extends AbstractConstraint
+{
+    /**
+     * @var FixtureFactory
+     */
+    protected $fixtureFactory;
+
+    /**
+     * Skip fields for create product fixture.
+     *
+     * @var array
+     */
+    protected $skipFields = [
+        'attribute_set_id',
+        'website_ids',
+        'checkout_data',
+        'type_id',
+        'price',
+    ];
+
+    /**
+     * AssertFirstProductForm constructor.
+     * @param ObjectManager $objectManager
+     */
+    public function __construct(
+        ObjectManager $objectManager,
+        EventManagerInterface $eventManager,
+        FixtureFactory $fixtureFactory
+    ) {
+        $this->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 9d19d10f4d40c6c3e317a97e7e83cd3c79e6f8ae..92b341bef2675fe635f804da2d9a17c5eea54c49 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
@@ -90,32 +90,7 @@ class CreateCreditMemoEntityTest extends Injectable
 
         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 02b9640acbea4159c0560e8a4727a13cc36e1199..b2cf9843598f48af778edda5a4240409fd9d0365 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
@@ -22,7 +22,7 @@
             <constraint name="Magento\Sales\Test\Constraint\AssertRefundOrderStatusInCommentsHistory" />
             <constraint name="Magento\Sales\Test\Constraint\AssertOrderCommentsHistoryNotifyStatus" />
             <constraint name="Magento\Sales\Test\Constraint\AssertRefundedGrandTotalOnFrontend" />
-            <constraint name="Magento\Catalog\Test\Constraint\AssertProductForm" />
+            <constraint name="Magento\Sales\Test\Constraint\AssertProductQtyDecreasedAfterCreditmemo" />
             <constraint name="Magento\Sales\Test\Constraint\AssertCreditMemoItems" />
         </variation>
         <variation name="CreateCreditMemoEntityTestVariation2" summary="Assert 0 shipping refund">