diff --git a/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/StockRepository/PreventDeleting/AssignedToSalesChannelsStockPlugin.php b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/StockRepository/PreventDeleting/AssignedToSalesChannelsStockPlugin.php
new file mode 100644
index 000000000000..3105844520f0
--- /dev/null
+++ b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/StockRepository/PreventDeleting/AssignedToSalesChannelsStockPlugin.php
@@ -0,0 +1,49 @@
+assignedSalesChannelsForStock = $assignedSalesChannelsForStock;
+ }
+
+ /**
+ * Prevent deleting of Stock which assigned at least one Sales Channel
+ *
+ * @param StockRepositoryInterface $subject
+ * @param int $stockId
+ * @return void
+ * @throws CouldNotDeleteException
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function beforeDeleteById(StockRepositoryInterface $subject, int $stockId)
+ {
+ $assignSalesChannels = $this->assignedSalesChannelsForStock->execute($stockId);
+ if (count($assignSalesChannels)) {
+ throw new CouldNotDeleteException(__('Stock has at least one sale channel and could not be deleted.'));
+ }
+ }
+}
diff --git a/app/code/Magento/InventoryCatalog/Plugin/Model/StockRepositoryPlugin.php b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/StockRepository/PreventDeleting/DefaultStockPlugin.php
similarity index 75%
rename from app/code/Magento/InventoryCatalog/Plugin/Model/StockRepositoryPlugin.php
rename to app/code/Magento/InventoryCatalog/Plugin/InventoryApi/StockRepository/PreventDeleting/DefaultStockPlugin.php
index a44f014c80e3..a4852c5c8d94 100644
--- a/app/code/Magento/InventoryCatalog/Plugin/Model/StockRepositoryPlugin.php
+++ b/app/code/Magento/InventoryCatalog/Plugin/InventoryApi/StockRepository/PreventDeleting/DefaultStockPlugin.php
@@ -3,17 +3,18 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
-namespace Magento\InventoryCatalog\Plugin\Model;
+namespace Magento\InventoryCatalog\Plugin\InventoryApi\StockRepository\PreventDeleting;
use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\InventoryApi\Api\StockRepositoryInterface;
use Magento\InventoryCatalog\Api\DefaultStockProviderInterface;
/**
- * Class provide Before Plugin on StockRepositoryInterface::deleteByItem to prevent default stock could be deleted
+ * Prevent deleting of Default Stock
*/
-class StockRepositoryPlugin
+class DefaultStockPlugin
{
/**
* @var DefaultStockProviderInterface
@@ -23,17 +24,17 @@ class StockRepositoryPlugin
/**
* @param DefaultStockProviderInterface $defaultStockProvider
*/
- public function __construct(DefaultStockProviderInterface $defaultStockProvider)
- {
+ public function __construct(
+ DefaultStockProviderInterface $defaultStockProvider
+ ) {
$this->defaultStockProvider = $defaultStockProvider;
}
/**
- * Prevent default source to be deleted
+ * Prevent deleting of Default Stock
*
* @param StockRepositoryInterface $subject
* @param int $stockId
- *
* @return void
* @throws CouldNotDeleteException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
diff --git a/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/PreventAssignedToSalesChannelsStockDeletingTest.php b/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/PreventAssignedToSalesChannelsStockDeletingTest.php
new file mode 100644
index 000000000000..331285ff9f10
--- /dev/null
+++ b/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/PreventAssignedToSalesChannelsStockDeletingTest.php
@@ -0,0 +1,52 @@
+ [
+ 'resourcePath' => '/V1/inventory/stock/' . $stockId,
+ 'httpMethod' => Request::HTTP_METHOD_DELETE,
+ ],
+ 'soap' => [
+ 'service' => 'inventoryApiStockRepositoryV1',
+ 'operation' => 'inventoryApiStockRepositoryV1DeleteById',
+ ],
+ ];
+ $expectedMessage = 'Stock has at least one sale channel and could not be deleted.';
+ try {
+ (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST)
+ ? $this->_webApiCall($serviceInfo)
+ : $this->_webApiCall($serviceInfo, ['stockId' => $stockId]);
+ $this->fail('Expected throwing exception');
+ } catch (\Exception $e) {
+ if (TESTS_WEB_API_ADAPTER == self::ADAPTER_REST) {
+ $errorData = $this->processRestExceptionResult($e);
+ self::assertEquals($expectedMessage, $errorData['message']);
+ self::assertEquals(Exception::HTTP_BAD_REQUEST, $e->getCode());
+ } elseif (TESTS_WEB_API_ADAPTER == self::ADAPTER_SOAP) {
+ $this->assertInstanceOf('SoapFault', $e);
+ $this->checkSoapFault($e, $expectedMessage, 'env:Sender');
+ } else {
+ throw $e;
+ }
+ }
+ }
+}
diff --git a/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/CouldNotDeleteDefaultStockExceptionTest.php b/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/PreventDefaultStockDeletingTest.php
similarity index 92%
rename from app/code/Magento/InventoryCatalog/Test/Api/StockRepository/CouldNotDeleteDefaultStockExceptionTest.php
rename to app/code/Magento/InventoryCatalog/Test/Api/StockRepository/PreventDefaultStockDeletingTest.php
index 0e2a002f53ca..d17b73a05bc2 100644
--- a/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/CouldNotDeleteDefaultStockExceptionTest.php
+++ b/app/code/Magento/InventoryCatalog/Test/Api/StockRepository/PreventDefaultStockDeletingTest.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
namespace Magento\InventoryCatalog\Test\Api\StockRepository;
@@ -12,10 +13,7 @@
use Magento\TestFramework\Helper\Bootstrap;
use Magento\InventoryCatalog\Api\DefaultStockProviderInterface;
-/**
- * Class CouldNotDeleteDefaultStockExceptionTest
- */
-class CouldNotDeleteDefaultStockExceptionTest extends WebapiAbstract
+class PreventDefaultStockDeletingTest extends WebapiAbstract
{
/**
* @var DefaultStockProviderInterface
@@ -32,8 +30,6 @@ protected function setUp()
}
/**
- * Test that default Stock could not be deleted
- *
* @throws \Exception
*/
public function testCouldNotDeleteException()
diff --git a/app/code/Magento/InventoryCatalog/Ui/Component/Control/Stock/DeleteButton.php b/app/code/Magento/InventoryCatalog/Ui/Component/Control/Stock/DeleteButton.php
index 7b8e2546bcec..f9e20031d3b8 100644
--- a/app/code/Magento/InventoryCatalog/Ui/Component/Control/Stock/DeleteButton.php
+++ b/app/code/Magento/InventoryCatalog/Ui/Component/Control/Stock/DeleteButton.php
@@ -3,6 +3,7 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
namespace Magento\InventoryCatalog\Ui\Component\Control\Stock;
@@ -11,10 +12,11 @@
use Magento\InventoryApi\Api\Data\StockInterface;
use Magento\InventoryCatalog\Api\DefaultStockProviderInterface;
use Magento\Framework\App\RequestInterface;
+use Magento\InventorySales\Model\GetAssignedSalesChannelsForStockInterface;
/**
* Represents delete button with pre-configured options
- * Provide an ability to show delete button only when stock id is not default
+ * Provide an ability to show delete button only when stock id is not default or doesn't have assigned sales channels
*/
class DeleteButton implements ButtonProviderInterface
{
@@ -28,6 +30,11 @@ class DeleteButton implements ButtonProviderInterface
*/
private $defaultStockProvider;
+ /**
+ * @var GetAssignedSalesChannelsForStockInterface
+ */
+ private $assignedSalesChannelsForStock;
+
/**
* @var RequestInterface
*/
@@ -36,15 +43,18 @@ class DeleteButton implements ButtonProviderInterface
/**
* @param StockDeleteButton $deleteButton
* @param DefaultStockProviderInterface $defaultStockProvider
+ * @param GetAssignedSalesChannelsForStockInterface $assignedSalesChannelsForStock
* @param RequestInterface $request
*/
public function __construct(
StockDeleteButton $deleteButton,
DefaultStockProviderInterface $defaultStockProvider,
+ GetAssignedSalesChannelsForStockInterface $assignedSalesChannelsForStock,
RequestInterface $request
) {
$this->deleteButton = $deleteButton;
$this->defaultStockProvider = $defaultStockProvider;
+ $this->assignedSalesChannelsForStock = $assignedSalesChannelsForStock;
$this->request = $request;
}
@@ -53,7 +63,9 @@ public function __construct(
*/
public function getButtonData()
{
- if ((int)$this->request->getParam(StockInterface::STOCK_ID) === $this->defaultStockProvider->getId()) {
+ $stockId = (int)$this->request->getParam(StockInterface::STOCK_ID);
+ $assignSalesChannels = $this->assignedSalesChannelsForStock->execute($stockId);
+ if ($stockId === $this->defaultStockProvider->getId() || count($assignSalesChannels)) {
return [];
}
diff --git a/app/code/Magento/InventoryCatalog/etc/di.xml b/app/code/Magento/InventoryCatalog/etc/di.xml
index 997bbe26b3c4..d7e40373206c 100644
--- a/app/code/Magento/InventoryCatalog/etc/di.xml
+++ b/app/code/Magento/InventoryCatalog/etc/di.xml
@@ -9,6 +9,9 @@
-
+
+
diff --git a/app/code/Magento/InventorySalesApi/Test/_files/stock_with_sales_channels_rollback.php b/app/code/Magento/InventorySalesApi/Test/_files/stock_with_sales_channels_rollback.php
index de50c82457f7..aa40d2e6d91e 100644
--- a/app/code/Magento/InventorySalesApi/Test/_files/stock_with_sales_channels_rollback.php
+++ b/app/code/Magento/InventorySalesApi/Test/_files/stock_with_sales_channels_rollback.php
@@ -8,4 +8,10 @@
/** @var StockRepositoryInterface $stockRepository */
$stockRepository = Bootstrap::getObjectManager()->get(StockRepositoryInterface::class);
+
+// Firstly clear relations with sales channels
+$stock = $stockRepository->get(10);
+$stock->getExtensionAttributes()->setSalesChannels([]);
+$stockRepository->save($stock);
+
$stockRepository->deleteById(10);
diff --git a/dev/tests/integration/phpunit.xml.dist b/dev/tests/integration/phpunit.xml.dist
index cca9c1e81f2c..6a7a70fe2cf7 100644
--- a/dev/tests/integration/phpunit.xml.dist
+++ b/dev/tests/integration/phpunit.xml.dist
@@ -54,7 +54,7 @@
-
+