Skip to content

Commit 579f6e5

Browse files
committed
ACP2E-262: Bundle product status in backend does not change automatically
1 parent 1c9a4dd commit 579f6e5

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

dev/tests/integration/testsuite/Magento/Bundle/Model/ProductTest.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,18 @@
1212

1313
use Magento\Bundle\Model\Product\Price;
1414
use Magento\Bundle\Model\Product\Type as BundleType;
15+
use Magento\Catalog\Api\Data\ProductInterface;
1516
use Magento\Catalog\Api\ProductRepositoryInterface;
1617
use Magento\Catalog\Model\Product;
1718
use Magento\Catalog\Model\Product\Attribute\Source\Status;
1819
use Magento\Catalog\Model\Product\Type;
1920
use Magento\Catalog\Model\Product\Visibility;
21+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
22+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
23+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
24+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
2025
use Magento\CatalogInventory\Model\Stock;
26+
use Magento\Framework\Exception\NoSuchEntityException;
2127
use Magento\Framework\ObjectManagerInterface;
2228
use Magento\Store\Api\StoreRepositoryInterface;
2329
use Magento\Store\Model\StoreManagerInterface;
@@ -250,6 +256,134 @@ public function stockConfigDataProvider(): array
250256
return $variations;
251257
}
252258

259+
/**
260+
* @magentoAppIsolation enabled
261+
* @magentoDataFixture Magento/Bundle/_files/bundle_product_with_dynamic_price.php
262+
* @dataProvider shouldUpdateBundleStockStatusIfChildProductsStockStatusChangedDataProvider
263+
* @param bool $isOption1Required
264+
* @param bool $isOption2Required
265+
* @param array $outOfStockConfig
266+
* @param array $inStockConfig
267+
* @throws NoSuchEntityException
268+
* @throws \Magento\Framework\Exception\CouldNotSaveException
269+
* @throws \Magento\Framework\Exception\InputException
270+
* @throws \Magento\Framework\Exception\StateException
271+
*/
272+
public function testShouldUpdateBundleStockStatusIfChildProductsStockStatusChanged(
273+
bool $isOption1Required,
274+
bool $isOption2Required,
275+
array $outOfStockConfig,
276+
array $inStockConfig
277+
): void {
278+
$sku = 'bundle_product_with_dynamic_price';
279+
/** @var ProductRepositoryInterface $productRepository */
280+
$productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
281+
/** @var ProductInterface $product */
282+
$product = $productRepository->get($sku, true, null, true);
283+
$extension = $product->getExtensionAttributes();
284+
$options = $extension->getBundleProductOptions();
285+
$options[0]->setRequired($isOption1Required);
286+
$options[1]->setRequired($isOption2Required);
287+
$extension->setBundleProductOptions($options);
288+
$stockItem = $extension->getStockItem();
289+
$stockItem->setUseConfigManageStock(1);
290+
$product->setExtensionAttributes($extension);
291+
$productRepository->save($product);
292+
293+
$stockItem = $this->getStockItem((int) $product->getId());
294+
$this->assertNotNull($stockItem);
295+
$this->assertTrue($stockItem->getIsInStock());
296+
foreach ($outOfStockConfig as $childSku => $stockData) {
297+
$this->updateStockItem($childSku, $stockData);
298+
}
299+
300+
$stockItem = $this->getStockItem((int) $product->getId());
301+
$this->assertNotNull($stockItem);
302+
$this->assertFalse($stockItem->getIsInStock());
303+
foreach ($inStockConfig as $childSku => $stockData) {
304+
$this->updateStockItem($childSku, $stockData);
305+
}
306+
307+
$stockItem = $this->getStockItem((int) $product->getId());
308+
$this->assertNotNull($stockItem);
309+
$this->assertTrue($stockItem->getIsInStock());
310+
}
311+
312+
/**
313+
* @return array
314+
*/
315+
public function shouldUpdateBundleStockStatusIfChildProductsStockStatusChangedDataProvider(): array
316+
{
317+
return [
318+
'all options are required' => [
319+
true,
320+
true,
321+
'out-of-stock' => [
322+
'simple1' => [
323+
'is_in_stock' => false
324+
],
325+
],
326+
'in-stock' => [
327+
'simple1' => [
328+
'is_in_stock' => true
329+
]
330+
]
331+
],
332+
'all options are optional' => [
333+
false,
334+
false,
335+
'out-of-stock' => [
336+
'simple1' => [
337+
'is_in_stock' => false
338+
],
339+
'simple2' => [
340+
'is_in_stock' => false
341+
],
342+
],
343+
'in-stock' => [
344+
'simple1' => [
345+
'is_in_stock' => true
346+
]
347+
]
348+
]
349+
];
350+
}
351+
352+
/**
353+
* @param string $sku
354+
* @param array $data
355+
* @throws NoSuchEntityException
356+
*/
357+
private function updateStockItem(string $sku, array $data): void
358+
{
359+
/** @var ProductRepositoryInterface $productRepository */
360+
$productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
361+
$product = $productRepository->get($sku, true, null, true);
362+
$extendedAttributes = $product->getExtensionAttributes();
363+
$stockItem = $extendedAttributes->getStockItem();
364+
$stockItem->setIsInStock($data['is_in_stock']);
365+
$extendedAttributes->setStockItem($stockItem);
366+
$product->setExtensionAttributes($extendedAttributes);
367+
$productRepository->save($product);
368+
}
369+
370+
/**
371+
* @param int $productId
372+
* @return StockItemInterface|null
373+
*/
374+
private function getStockItem(int $productId): ?StockItemInterface
375+
{
376+
$criteriaFactory = $this->objectManager->create(StockItemCriteriaInterfaceFactory::class);
377+
$stockItemRepository = $this->objectManager->create(StockItemRepositoryInterface::class);
378+
$stockConfiguration = $this->objectManager->create(StockConfigurationInterface::class);
379+
$criteria = $criteriaFactory->create();
380+
$criteria->setScopeFilter($stockConfiguration->getDefaultScopeId());
381+
$criteria->setProductsFilter($productId);
382+
$stockItemCollection = $stockItemRepository->getList($criteria);
383+
$stockItems = $stockItemCollection->getItems();
384+
return reset($stockItems);
385+
}
386+
253387
/**
254388
* @param float $selectionQty
255389
* @param float $qty

0 commit comments

Comments
 (0)