Skip to content

Commit 825c41a

Browse files
author
Mike Weis
committed
MAGETWO-28252: Catalog Inventory Integration API
- ensure a newly created product gets its catalog inventory created
1 parent 7f8c6a0 commit 825c41a

File tree

3 files changed

+92
-16
lines changed

3 files changed

+92
-16
lines changed

app/code/Magento/CatalogInventory/Model/Plugin/AroundProductRepositorySave.php

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,8 @@ public function aroundSave(
4848
/** @var \Magento\Catalog\Api\Data\ProductInterface $result */
4949
$result = $proceed($product, $saveOptions);
5050

51-
// all the data we care about will exist as extension attributes of the original product
52-
$extendedAttributes = $product->getExtensionAttributes();
53-
if ($extendedAttributes === null) {
54-
return $result;
55-
}
56-
5751
/* @var \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem */
58-
$stockItem = $extendedAttributes->getStockItem();
52+
$stockItem = $this->getStockItemToBeUpdated($product);
5953
if ($stockItem == null) {
6054
return $result;
6155
}
@@ -69,4 +63,33 @@ public function aroundSave(
6963
// since we just saved a portion of the product, force a reload of it before returning it
7064
return $subject->get($result->getSku(), false, $result->getStoreId(), true);
7165
}
66+
67+
/**
68+
* Return the stock item that needs to be updated.
69+
* If the stock item does not need to be updated, return null.
70+
*
71+
* @param \Magento\Catalog\Api\Data\ProductInterface $product
72+
* @return \Magento\CatalogInventory\Api\Data\StockItemInterface|null
73+
*/
74+
protected function getStockItemToBeUpdated($product)
75+
{
76+
// from the API, all the data we care about will exist as extension attributes of the original product
77+
$extendedAttributes = $product->getExtensionAttributes();
78+
if ($extendedAttributes !== null) {
79+
$stockItem = $extendedAttributes->getStockItem();
80+
if ($stockItem != null) {
81+
return $stockItem;
82+
}
83+
}
84+
85+
// we have no new stock item information to update, however we need to ensure that the product does have some
86+
// stock item information present. On a newly created product, it will not have any stock item info.
87+
$stockItem = $this->stockRegistry->getStockItem($product->getId());
88+
if ($stockItem->getItemId() != null) {
89+
// we already have stock item info, so we return null since nothing more needs to be updated
90+
return null;
91+
}
92+
93+
return $stockItem;
94+
}
7295
}

app/code/Magento/CatalogInventory/Test/Unit/Model/Plugin/AroundProductRepositorySaveTest.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,32 +78,55 @@ public function setUp()
7878
$this->stockItemMock = $this->getMock('\Magento\CatalogInventory\Api\Data\StockItemInterface');
7979
}
8080

81-
public function testAroundSaveWhenProductHasNoExtensionAttributes()
81+
public function testAroundSaveWhenProductHasNoStockItemNeedingToBeUpdated()
8282
{
83+
// pretend we have no extension attributes at all
8384
$this->productMock->expects($this->once())
8485
->method('getExtensionAttributes')
8586
->willReturn(null);
8687
$this->productExtensionMock->expects($this->never())->method('getStockItem');
8788

89+
// pretend that the product already has existing stock item information
90+
$this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($this->stockItemMock);
91+
$this->stockItemMock->expects($this->once())->method('getItemId')->willReturn(1);
92+
$this->stockItemMock->expects($this->never())->method('setProductId');
93+
$this->stockItemMock->expects($this->never())->method('setWebsiteId');
94+
95+
// expect that there are no changes to the existing stock item information
8896
$this->assertEquals(
8997
$this->savedProductMock,
9098
$this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock)
9199
);
92100
}
93101

94-
public function testAroundSaveWhenProductHasNoStockItemAttributes()
102+
public function testAroundSaveWhenProductHasNoPersistentStockItemInfo()
95103
{
104+
// pretend we do have extension attributes, but none for 'stock_item'
96105
$this->productMock->expects($this->once())
97106
->method('getExtensionAttributes')
98107
->willReturn($this->productExtensionMock);
99108
$this->productExtensionMock->expects($this->once())
100109
->method('getStockItem')
101110
->willReturn(null);
102-
$this->stockItemMock->expects($this->never())->method('setProductId');
103-
$this->stockItemMock->expects($this->never())->method('setWebsiteId');
111+
112+
$storeMock = $this->getMockBuilder('\Magento\Store\Model\Store')
113+
->disableOriginalConstructor()->getMock();
114+
$storeMock->expects($this->once())->method('getWebsiteId')->willReturn(1);
115+
$this->storeManager->expects($this->once())->method('getStore')->willReturn($storeMock);
116+
117+
$this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($this->stockItemMock);
118+
$this->stockRegistry->expects($this->once())->method('updateStockItemBySku');
119+
120+
$this->stockItemMock->expects($this->once())->method('getItemId')->willReturn(null);
121+
$this->stockItemMock->expects($this->once())->method('setProductId');
122+
$this->stockItemMock->expects($this->once())->method('setWebsiteId');
123+
124+
$newProductMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface')
125+
->disableOriginalConstructor()->getMock();
126+
$this->productRepositoryMock->expects($this->once())->method('get')->willReturn($newProductMock);
104127

105128
$this->assertEquals(
106-
$this->savedProductMock,
129+
$newProductMock,
107130
$this->plugin->aroundSave($this->productRepositoryMock, $this->closureMock, $this->productMock)
108131
);
109132
}

dev/tests/api-functional/testsuite/Magento/CatalogInventory/Api/ProductRepositoryInterfaceTest.php

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,31 @@ public function testCatalogInventoryWithBogusData()
155155
$this->assertTrue($response);
156156
}
157157

158+
/**
159+
* Tests that creating a simple product has a side-effect of creating catalog inventory
160+
*/
161+
public function testSimpleProductCreationWithoutSpecifyingCatalogInventory()
162+
{
163+
// create a simple product with catalog inventory
164+
$qty = null;
165+
$productData = $this->getSimpleProductData($qty);
166+
$this->assertArrayNotHasKey(self::KEY_CUSTOM_ATTRIBUTES, $productData);
167+
$this->assertArrayNotHasKey(self::KEY_EXTENSION_ATTRIBUTES, $productData);
168+
169+
$response = $this->saveProduct($productData);
170+
171+
$this->assertArrayHasKey(self::KEY_EXTENSION_ATTRIBUTES, $response);
172+
$this->assertTrue(isset($response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM]));
173+
$stockItemData = $response[self::KEY_EXTENSION_ATTRIBUTES][self::KEY_STOCK_ITEM];
174+
$this->assertArrayHasKey(self::KEY_ITEM_ID, $stockItemData);
175+
$this->assertArrayHasKey(self::KEY_PRODUCT_ID, $stockItemData);
176+
$this->assertArrayHasKey(self::KEY_WEBSITE_ID, $stockItemData);
177+
178+
// delete the product; expect that all goes well
179+
$response = $this->deleteProduct($productData[ProductInterface::SKU]);
180+
$this->assertTrue($response);
181+
}
182+
158183
// --- my helpers -----------------------------------------------------------------------------
159184

160185
/**
@@ -210,19 +235,24 @@ protected function findCustomAttributeQty($customAttributes)
210235
*/
211236
protected function getSimpleProductData($qty = 1000)
212237
{
213-
return [
238+
$productData = [
214239
ProductInterface::SKU => self::PRODUCT_SKU,
215240
ProductInterface::NAME => self::PRODUCT_SKU,
216241
ProductInterface::VISIBILITY => 4,
217242
ProductInterface::TYPE_ID => 'simple',
218243
ProductInterface::PRICE => 10,
219244
ProductInterface::STATUS => 1,
220245
ProductInterface::ATTRIBUTE_SET_ID => 4,
221-
self::KEY_CUSTOM_ATTRIBUTES => [
246+
];
247+
248+
if ($qty != null) {
249+
$productData[self::KEY_CUSTOM_ATTRIBUTES] = [
222250
[self::KEY_ATTRIBUTE_CODE => 'description', 'value' => 'My Product Description'],
223251
[self::KEY_ATTRIBUTE_CODE => self::CODE_QUANTITY_AND_STOCK_STATUS, 'value' => [true, $qty]],
224-
],
225-
];
252+
];
253+
}
254+
255+
return $productData;
226256
}
227257

228258
/**

0 commit comments

Comments
 (0)