How to programmatically create source and assign to stock in Magento2

Written by Jigar Patel

Jan 08, 2023

How to programmatically create source and assign to stock in Magento2

What is MSI – Magento2 Multi Source Inventory (MSI) is newly introduced in Magento 2.3 version(upcoming release) which is used to manage inventory by source (location).

You can get the Magento 2.3 Multi-Source Inventory (MSI) version from https://github.com/magento-engcom/msi.

MSI is a considerable improvement to the Magento core, which connects multiple inventory sources to your e-commerce website.

You can assign multiple sources and sales channels to one stock. But keep in mind, that one sales channel can be connected to one stock only. In this context, a sales channel is actually your Magento website.

Here I’ll show you How to programmatically create a source and assign it to stock in Magento2.

I have created a method InventorySource in the following Helper class file.

You can add this method to your required class file and call on the needed places in your code.

<?php

namespace Dolphin\CustomMsiNew\Helper;

use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Message\ManagerInterface;
use Magento\InventoryAdminUi\Model\Source\SourceHydrator as InventorySourceHydrator;
use Magento\InventoryApi\Api\Data\SourceInterface;
use Magento\InventoryApi\Api\Data\SourceInterfaceFactory;
use Magento\InventoryApi\Api\Data\StockSourceLinkInterface;
use Magento\InventoryApi\Api\Data\StockSourceLinkInterfaceFactory;
use Magento\InventoryApi\Api\GetStockSourceLinksInterface;
use Magento\InventoryApi\Api\SourceRepositoryInterface;
use Magento\InventoryApi\Api\StockSourceLinksSaveInterface;
use Magento\InventorySales\Model\GetAssignedStockIdForWebsiteInterface;
use Magento\Store\Model\StoreManagerInterface;

class InventorySource extends \Magento\Framework\App\Helper\AbstractHelper
{
    /**
     * @var SourceInterfaceFactory
     */
    private $sourceInterfaceFactory;
    /**
     * @var SourceRepositoryInterface
     */
    private $sourceRepositoryInterface;
    /**
     * @var InventorySourceHydrator
     */
    private $inventorySourceHydrator;
    /**
     * @var ManagerInterface
     */
    private $messageManager;
    /**
     * @var StoreManagerInterface
     */
    private $storeManager;
    /**
     * @var GetAssignedStockIdForWebsiteInterface
     */
    private $getAssignedStockIdForWebsite;
    /**
     * @var SearchCriteriaBuilder
     */
    private $searchCriteriaBuilder;
    /**
     * @var GetStockSourceLinksInterface
     */
    private $getStockSourceLinks;
    /**
     * @var StockSourceLinkInterfaceFactory
     */
    private $stockSourceLink;
    /**
     * @var DataObjectHelper
     */
    private $dataObject;
    /**
     * @var StockSourceLinksSaveInterface
     */
    private $stockSourceLinksSave;

    /**
     * @param \Magento\Framework\App\Helper\Context $context
     * @param SourceInterfaceFactory $sourceInterfaceFactory
     * @param SourceRepositoryInterface $sourceRepositoryInterface
     * @param InventorySourceHydrator $inventorySourceHydrator
     * @param ManagerInterface $messageManager
     * @param \Magento\Framework\Event\Manager $eventManager
     * @param StoreManagerInterface $storeManager
     * @param GetAssignedStockIdForWebsiteInterface $getAssignedStockIdForWebsite
     * @param SearchCriteriaBuilder $searchCriteriaBuilder
     * @param GetStockSourceLinksInterface $getStockSourceLinks
     * @param StockSourceLinkInterfaceFactory $stockSourceLink
     * @param DataObjectHelper $dataObject
     * @param StockSourceLinksSaveInterface $stockSourceLinksSave
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        SourceInterfaceFactory $sourceInterfaceFactory,
        SourceRepositoryInterface $sourceRepositoryInterface,
        InventorySourceHydrator $inventorySourceHydrator,
        ManagerInterface $messageManager,
        StoreManagerInterface $storeManager,
        GetAssignedStockIdForWebsiteInterface $getAssignedStockIdForWebsite,
        SearchCriteriaBuilder $searchCriteriaBuilder,
        GetStockSourceLinksInterface $getStockSourceLinks,
        StockSourceLinkInterfaceFactory $stockSourceLink,
        DataObjectHelper $dataObject,
        StockSourceLinksSaveInterface $stockSourceLinksSave
    )
    {
        $this->_request = $context->getRequest();
        $this->sourceInterfaceFactory = $sourceInterfaceFactory;
        $this->sourceRepositoryInterface = $sourceRepositoryInterface;
        $this->inventorySourceHydrator = $inventorySourceHydrator;
        $this->messageManager = $messageManager;
        $this->storeManager = $storeManager;
        $this->getAssignedStockIdForWebsite = $getAssignedStockIdForWebsite;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        $this->getStockSourceLinks = $getStockSourceLinks;
        $this->stockSourceLink = $stockSourceLink;
        $this->dataObject = $dataObject;
        $this->stockSourceLinksSave = $stockSourceLinksSave;
        parent::__construct($context);
    }

    public function prepareSourceRequestData()
    {
        $sourceCode = null;
        $request = $this->_request;
        $sourceData = [];
        $sourceData['id_field_name'] = 'source_code';
        $sourceData['source_code'] = 'us-florida';
        $sourceData['name'] = 'US Florida';
        $sourceData['email'] = '';
        $sourceData['contact_name'] = '';
        $sourceData['enabled'] = 1;
        $sourceData['description'] = '';
        $sourceData['latitude'] = '';
        $sourceData['longitude'] = '';
        $sourceData['country_id'] = 'US';
        $sourceData['region_id'] = 12;
        $sourceData['city'] = '';
        $sourceData['postcode'] = '95004';
        $sourceData['use_default_carrier_config'] = 1;
        $sourceData['carrier_codes'] = '';
        $sourceData['disable_source_code'] = true;
        $sourceData['phone'] = '';
        $sourceData['fax'] = '';
        $sourceData['region'] = '';
        $sourceData['street'] = '';
        $request->setPostValue('general', $sourceData);
        $request->setPostValue('form_key', 'or1eYs7K4PBsLbO1');
    }

    public function processSource()
    {
        // prepare source request data
        $this->prepareSourceRequestData();
        $sourceCode = null;
        $newSourceData = [];
        $request = $this->_request;
        $requestData = $request->getPost()->toArray();
        $sourceCodeQueryParam = $request->getQuery(SourceInterface::SOURCE_CODE);
        try {
            $inventorySource = (null !== $sourceCodeQueryParam)
                ? $this->sourceRepositoryInterface->get($sourceCodeQueryParam)
                : $this->sourceInterfaceFactory->create();
            $inventorySource = $this->inventorySourceHydrator->hydrate($inventorySource, $requestData);
            $this->_eventManager->dispatch(
                'controller_action_inventory_populate_source_with_data',
                [
                    'request' => $request,
                    'source' => $inventorySource,
                ]
            );
            $this->sourceRepositoryInterface->save($inventorySource);
            $this->_eventManager->dispatch(
                'controller_action_inventory_source_save_after',
                [
                    'request' => $request,
                    'source' => $inventorySource,
                ]
            );
            $sourceCode = $requestData['general']['source_code'];
            $newSourceData['source_code'] = $sourceCode;
            $newSourceData['name'] = $requestData['general']['name'];
            $newSourceData['position'] = 1;
            $newSourceData['record_id'] = $sourceCode;
            $newSourceData['priority'] = 1;
            $this->messageManager->addSuccessMessage(__('The Source has been saved.'));
        } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
            $sourceCode = 0;
            $this->messageManager->addErrorMessage(__('The Source does not exist.'));
        } catch (\Magento\Framework\Validation\ValidationException $e) {
            $sourceCode = 0;
            foreach ($e->getErrors() as $localizedError) {
                $this->messageManager->addErrorMessage($localizedError->getMessage());
            }
        } catch (\Magento\Framework\Exception\CouldNotSaveException $e) {
            $sourceCode = 0;
            $this->messageManager->addErrorMessage($e->getMessage());
        } catch (\Exception $e) {
            $sourceCode = 0;
            $this->messageManager->addErrorMessage(__('Could not save Source.'));
        }
        $this->assignSourceToStocks($sourceCode, $newSourceData);
    }

    public function assignSourceToStocks($sourceCode, $newSourceData)
    {
        try {
            if ($sourceCode) {
                $allWebsites = $this->storeManager->getWebsites();
                foreach ($allWebsites as $website) {
                    $websiteCode = $website->getCode();
                    $stockId = $this->getAssignedStockIdForWebsite->execute($websiteCode);
                    $searchCriteria = $this->searchCriteriaBuilder->addFilter(
                        StockSourceLinkInterface::STOCK_ID,
                        $stockId
                    )->create();
                    $result = [];
                    foreach ($this->getStockSourceLinks->execute($searchCriteria)->getItems() as $link) {
                        $result[$link->getSourceCode()] = $link;
                    }
                    if (isset($result[$sourceCode])) {
                        $link = $result[$sourceCode];
                    } else {
                        /** @var StockSourceLinkInterface $link */
                        $link = $this->stockSourceLink->create();
                    }
                    $newSourceData[StockSourceLinkInterface::STOCK_ID] = $stockId;
                    $this->dataObject->populateWithArray($link, $newSourceData, StockSourceLinkInterface::class);
                    $result[] = $link;
                    if (!empty($result)) {
                        $this->stockSourceLinksSave->execute($result);
                    }
                }
            }
        } catch (\Exception $e) {
            $this->messageManager->addErrorMessage(__('Could not save Source to Stock.'));
        }
    }
}

Follow the above class to create a source and assign it to stock in Magento2.

I Hope, This instruction will be helpful for you.

Happy Coding with magento2!! 🙂

If you have any difficulties regarding this blog, do consider them posting in the Comments section below!

I’m here to help.

Thank you!

Jigar Patel

Author

We can help you with

  • Dedicated Team
  • Setup Extended Team
  • Product Development
  • Custom App Development

Schedule a Developer Interview And Get 7 Days Risk-Free Trial

Fill out This Form and one of Our Technical Experts will Contact you Within 12 Hours.

    Google
    |

    4.8

    Google
    |

    4.8

    Google
    |

    4.9

    Google
    |

    4.8

    Google
    |

    4.9

    Copyright © 2024 DOLPHIN WEB SOLUTION. All rights reserved.

    TO TOP