diff --git a/app/code/Magento/InventorySales/Model/DeleteSalesChannelToStockLinkInterface.php b/app/code/Magento/InventorySales/Model/DeleteSalesChannelToStockLinkInterface.php
new file mode 100644
index 000000000000..e37fde06b485
--- /dev/null
+++ b/app/code/Magento/InventorySales/Model/DeleteSalesChannelToStockLinkInterface.php
@@ -0,0 +1,23 @@
+resourceConnection = $resourceConnection;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(string $type, string $code)
+ {
+ $connection = $this->resourceConnection->getConnection();
+ $tableName = $this->resourceConnection->getTableName(CreateSalesChannelTable::TABLE_NAME_SALES_CHANNEL);
+
+ $connection->delete($tableName, [
+ SalesChannelInterface::TYPE . ' = ?' => $type,
+ SalesChannelInterface::CODE . ' = ?' => $code,
+ ]);
+ }
+}
diff --git a/app/code/Magento/InventorySales/Model/ResourceModel/GetAssignedStockIdForWebsite.php b/app/code/Magento/InventorySales/Model/ResourceModel/GetAssignedStockIdForWebsite.php
new file mode 100644
index 000000000000..d82a2da57ca1
--- /dev/null
+++ b/app/code/Magento/InventorySales/Model/ResourceModel/GetAssignedStockIdForWebsite.php
@@ -0,0 +1,54 @@
+resourceConnection = $resourceConnection;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(string $websiteCode)
+ {
+ $connection = $this->resourceConnection->getConnection();
+ $tableName = $this->resourceConnection->getTableName(CreateSalesChannelTable::TABLE_NAME_SALES_CHANNEL);
+
+ $select = $connection->select()
+ ->from($tableName, [CreateSalesChannelTable::STOCK_ID])
+ ->where('code = ?', $websiteCode)
+ ->where('type = ?', SalesChannelInterface::TYPE_WEBSITE);
+
+ $result = $connection->fetchCol($select);
+
+ if (count($result) === 0) {
+ return null;
+ }
+ return reset($result);
+ }
+}
diff --git a/app/code/Magento/InventorySales/Model/ResourceModel/ReplaceSalesChannelsDataForStock.php b/app/code/Magento/InventorySales/Model/ResourceModel/ReplaceSalesChannelsDataForStock.php
index 567f53ad4a7d..1f967aa4e5b8 100644
--- a/app/code/Magento/InventorySales/Model/ResourceModel/ReplaceSalesChannelsDataForStock.php
+++ b/app/code/Magento/InventorySales/Model/ResourceModel/ReplaceSalesChannelsDataForStock.php
@@ -35,11 +35,7 @@ public function __construct(
}
/**
- * Replace Sales Channels for Stock
- *
- * @param SalesChannelInterface[] $salesChannels
- * @param int $stockId
- * @return void
+ * @inheritdoc
*/
public function execute(array $salesChannels, int $stockId)
{
diff --git a/app/code/Magento/InventorySales/Observer/Stock/PopulateWithWebsiteSalesChannelsObserver.php b/app/code/Magento/InventorySales/Observer/Stock/PopulateWithWebsiteSalesChannelsObserver.php
index eb1242c9c0ea..3c73452baf11 100644
--- a/app/code/Magento/InventorySales/Observer/Stock/PopulateWithWebsiteSalesChannelsObserver.php
+++ b/app/code/Magento/InventorySales/Observer/Stock/PopulateWithWebsiteSalesChannelsObserver.php
@@ -49,9 +49,11 @@ public function execute(EventObserver $observer)
$extensionAttributes = $stock->getExtensionAttributes();
$assignedSalesChannels = $extensionAttributes->getSalesChannels();
- foreach ($assignedSalesChannels as $key => $assignedSalesChannel) {
- if ($assignedSalesChannel->getType() === SalesChannelInterface::TYPE_WEBSITE) {
- unset($assignedSalesChannels[$key]);
+ if (null !== $assignedSalesChannels) {
+ foreach ($assignedSalesChannels as $key => $assignedSalesChannel) {
+ if ($assignedSalesChannel->getType() === SalesChannelInterface::TYPE_WEBSITE) {
+ unset($assignedSalesChannels[$key]);
+ }
}
}
diff --git a/app/code/Magento/InventorySales/Observer/Website/AssignWebsiteToDefaultStock.php b/app/code/Magento/InventorySales/Observer/Website/AssignWebsiteToDefaultStock.php
new file mode 100644
index 000000000000..d913649f5739
--- /dev/null
+++ b/app/code/Magento/InventorySales/Observer/Website/AssignWebsiteToDefaultStock.php
@@ -0,0 +1,105 @@
+stockRepository = $stockRepository;
+ $this->defaultStockProvider = $defaultStockProvider;
+ $this->salesChannelFactory = $salesChannelFactory;
+ $this->getAssignedStockIdForWebsite = $getAssignedStockIdForWebsite;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(Observer $observer)
+ {
+ /** @var Website $website */
+ $website = $observer->getData('website');
+ $websiteCode = $website->getCode();
+
+ if ($websiteCode === WebsiteInterface::ADMIN_CODE) {
+ return;
+ }
+
+ // checks is some stock already assigned to this website
+ if ($this->getAssignedStockIdForWebsite->execute($websiteCode) !== null) {
+ return;
+ }
+
+ $defaultStockId = $this->defaultStockProvider->getId();
+ $defaultStock = $this->stockRepository->get($defaultStockId);
+
+ $extensionAttributes = $defaultStock->getExtensionAttributes();
+ $salesChannels = $extensionAttributes->getSalesChannels();
+ $salesChannels[] = $this->createSalesChannelByWebsiteCode($websiteCode);
+
+ $extensionAttributes->setSalesChannels($salesChannels);
+ $this->stockRepository->save($defaultStock);
+ }
+
+ /**
+ * Create the sales channel by given website code
+ *
+ * @param string $websiteCode
+ * @return SalesChannelInterface
+ */
+ private function createSalesChannelByWebsiteCode(string $websiteCode): SalesChannelInterface
+ {
+ $salesChannel = $this->salesChannelFactory->create();
+ $salesChannel->setCode($websiteCode);
+ $salesChannel->setType(SalesChannelInterface::TYPE_WEBSITE);
+ return $salesChannel;
+ }
+}
diff --git a/app/code/Magento/InventorySales/Observer/Website/DeleteWebsiteToStockLink.php b/app/code/Magento/InventorySales/Observer/Website/DeleteWebsiteToStockLink.php
new file mode 100644
index 000000000000..47e182a1feae
--- /dev/null
+++ b/app/code/Magento/InventorySales/Observer/Website/DeleteWebsiteToStockLink.php
@@ -0,0 +1,50 @@
+deleteSalesChannelToStockLink = $deleteSalesChannelToStockLink;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function execute(Observer $observer)
+ {
+ /** @var Website $website */
+ $website = $observer->getData('website');
+ $websiteCode = $website->getCode();
+
+ if ($websiteCode === WebsiteInterface::ADMIN_CODE) {
+ return;
+ }
+ $this->deleteSalesChannelToStockLink->execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode);
+ }
+}
diff --git a/app/code/Magento/InventorySales/Test/Integration/Website/AssignWebsiteToDefaultStockTest.php b/app/code/Magento/InventorySales/Test/Integration/Website/AssignWebsiteToDefaultStockTest.php
new file mode 100644
index 000000000000..b9fd61ea6c08
--- /dev/null
+++ b/app/code/Magento/InventorySales/Test/Integration/Website/AssignWebsiteToDefaultStockTest.php
@@ -0,0 +1,68 @@
+websiteFactory = Bootstrap::getObjectManager()->get(WebsiteFactory::class);
+ $this->stockRepository = Bootstrap::getObjectManager()->get(StockRepositoryInterface::class);
+ $this->defaultStockProvider = Bootstrap::getObjectManager()->get(DefaultStockProviderInterface::class);
+ }
+
+ /**
+ * Creates website inside of test so need to enable db isolation to prevent change db state after test execution
+ * @magentoDbIsolation enabled
+ */
+ public function testCreateWebsiteIfSalesChannelsAreEmpty()
+ {
+ $websiteCode = 'test_1';
+
+ /** @var Website $website */
+ $website = $this->websiteFactory->create();
+ $website->setCode($websiteCode);
+ // Use website model because we haven't api interfaces for website saving
+ $website->save();
+
+ $defaultStockId = $this->defaultStockProvider->getId();
+ $defaultStock = $this->stockRepository->get($defaultStockId);
+
+ $extensionAttributes = $defaultStock->getExtensionAttributes();
+ $salesChannels = $extensionAttributes->getSalesChannels();
+ self::assertContainsOnlyInstancesOf(SalesChannelInterface::class, $salesChannels);
+ self::assertCount(1, $salesChannels);
+
+ $salesChannel = reset($salesChannels);
+ self::assertEquals($website->getCode(), $salesChannel->getCode());
+ self::assertEquals(SalesChannelInterface::TYPE_WEBSITE, $salesChannel->getType());
+ }
+}
diff --git a/app/code/Magento/InventorySales/Test/Integration/Website/DeleteWebsiteToStockLinkTest.php b/app/code/Magento/InventorySales/Test/Integration/Website/DeleteWebsiteToStockLinkTest.php
new file mode 100644
index 000000000000..05d45ba35962
--- /dev/null
+++ b/app/code/Magento/InventorySales/Test/Integration/Website/DeleteWebsiteToStockLinkTest.php
@@ -0,0 +1,69 @@
+websiteFactory = Bootstrap::getObjectManager()->get(WebsiteFactory::class);
+ $this->getAssignedStockIdForWebsite = Bootstrap::getObjectManager()->get(
+ GetAssignedStockIdForWebsiteInterface::class
+ );
+ }
+
+ /**
+ * Creates website inside of test so need to enable db isolation to prevent change db state after test execution
+ * @magentoDbIsolation enabled
+ */
+ public function testGetAssignedStocksForWebsite()
+ {
+ $websiteCode = 'test_1';
+
+ /** @var Website $website */
+ $website = $this->websiteFactory->create();
+ $website->setCode($websiteCode);
+ // Use website model because we haven't api interfaces for website saving/deleting
+ $website->save();
+ $this->deleteWebsite($website);
+
+ $stockId = $this->getAssignedStockIdForWebsite->execute($websiteCode);
+ self::assertNull($stockId);
+ }
+
+ /**
+ * @param Website $website
+ * @return void
+ */
+ private function deleteWebsite(Website $website)
+ {
+ $registry = Bootstrap::getObjectManager()->get(Registry::class);
+ $registry->unregister('isSecureArea');
+ $registry->register('isSecureArea', true);
+ $website->delete();
+ $registry->unregister('isSecureArea');
+ $registry->register('isSecureArea', false);
+ }
+}
diff --git a/app/code/Magento/InventorySales/Test/Integration/Website/GetAssignedStockIdForWebsiteTest.php b/app/code/Magento/InventorySales/Test/Integration/Website/GetAssignedStockIdForWebsiteTest.php
new file mode 100644
index 000000000000..288aa04566ba
--- /dev/null
+++ b/app/code/Magento/InventorySales/Test/Integration/Website/GetAssignedStockIdForWebsiteTest.php
@@ -0,0 +1,65 @@
+websiteFactory = Bootstrap::getObjectManager()->get(WebsiteFactory::class);
+ $this->getAssignedStockIdForWebsite = Bootstrap::getObjectManager()->get(
+ GetAssignedStockIdForWebsiteInterface::class
+ );
+ $this->defaultStockProvider = Bootstrap::getObjectManager()->get(DefaultStockProviderInterface::class);
+ }
+
+ public function testGetAssignedStocksForNotExistedWebsite()
+ {
+ self::assertNull($this->getAssignedStockIdForWebsite->execute('not_existed_website_code'));
+ }
+
+ /**
+ * Creates website inside of test so need to enable db isolation to prevent change db state after test execution
+ * @magentoDbIsolation enabled
+ */
+ public function testGetAssignedStocksForWebsite()
+ {
+ $websiteCode = 'test_1';
+
+ /** @var Website $website */
+ $website = $this->websiteFactory->create();
+ $website->setCode($websiteCode);
+ // Use website model because we haven't api interfaces for website saving
+ $website->save();
+
+ $stockId = $this->getAssignedStockIdForWebsite->execute($websiteCode);
+ self::assertEquals($this->defaultStockProvider->getId(), $stockId);
+ }
+}
diff --git a/app/code/Magento/InventorySales/etc/di.xml b/app/code/Magento/InventorySales/etc/di.xml
index 87feda242e6c..5d4c7be74aaf 100644
--- a/app/code/Magento/InventorySales/etc/di.xml
+++ b/app/code/Magento/InventorySales/etc/di.xml
@@ -11,6 +11,8 @@
+
+
diff --git a/app/code/Magento/InventorySales/etc/events.xml b/app/code/Magento/InventorySales/etc/events.xml
new file mode 100644
index 000000000000..214d97feeb2d
--- /dev/null
+++ b/app/code/Magento/InventorySales/etc/events.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/website_attribute_sync_rollback.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/website_attribute_sync_rollback.php
index 7505e3430d53..307dbede649e 100644
--- a/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/website_attribute_sync_rollback.php
+++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/ResourceModel/_files/website_attribute_sync_rollback.php
@@ -76,12 +76,10 @@
/**
* remove website by id
*/
-$connection->delete(
- $resourceConnection->getTableName('store_website'),
- [
- 'website_id = ?' => $websiteId,
- ]
-);
+/** @var \Magento\Store\Model\Website $website */
+$website = Bootstrap::getObjectManager()->create(\Magento\Store\Model\Website::class);
+$website->load((int)$websiteId);
+$website->delete();
/**
* reIndex all