Magento – Assign Inventory source while programmatically creating product

magento2magento2.3magento2.3.0multi-source-inventoryproduct

I have a custom script that read CSV and creates products programmatically, it was working fine with Magento 2.2.6, now I upgraded it to Magento 2.3, and with upgradation, I configured Multi-Source Inventory. The issue I am facing is that while saving the product it is throwing error "The stock item was unable to be saved. Please try again."

I am getting below error in the log

 main.CRITICAL: The stock item was unable to be saved. Please try again. {"exception":"[object] (Magento\\Framework\\Exception\\CouldNotSaveException(code: 0): The stock item was unable to be saved. Please try again. at /magento_root/vendor/magento/module-catalog-inventory/Model/Stock/StockItemRepository.php:187,
 Magento\\Framework\\Exception\\CouldNotSaveException(code: 0): Could not save Source Item at /magento_root/vendor/magento/module-inventory/Model/SourceItem/Command/Handler/SourceItemsSaveHandler.php:78,
 Zend_Db_Statement_Exception(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`magento_db`.`inventory_source_item`, CONSTRAINT `INVENTORY_SOURCE_ITEM_SOURCE_CODE_INVENTORY_SOURCE_SOURCE_CODE` FOREIGN KEY (`source_code`) REFERENCES `inventory_source` (`source_code`) ON DEL), query was: INSERT INTO inventory_source_item (`source_code`, `sku`, `quantity`, `status`) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE `quantity` = VALUES(`quantity`), `status` = VALUES(`status`) at /magento_root/vendor/magento/zendframework1/library/Zend/Db/Statement/Pdo.php:235,
 PDOException(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`magento_db`.`inventory_source_item`, CONSTRAINT `INVENTORY_SOURCE_ITEM_SOURCE_CODE_INVENTORY_SOURCE_SOURCE_CODE` FOREIGN KEY (`source_code`) REFERENCES `inventory_source` (`source_code`) ON DEL) at /magento_root/vendor/magento/zendframework1/library/Zend/Db/Statement/Pdo.php:228)"} []

I Injected \Magento\Catalog\Model\ProductFactory $productFactory and using the below code to create the product

$_product = $this->_productFactory->create();

$mainImage = "";
$imagesToImport = "";
if (isset($productData['images'])) {
    $images = explode(',', $productData['images']);
    $mainImage = $images[0];
    array_shift($images);
    if (count($images) > 0) {
        if (count($images) > 1) {
            $imagesToImport = implode(';', $images);
        } else {
            $imagesToImport = $images[0];
        }
    }
}
$urlKey = $this->geturlKey($productData['name']);
$_product->setName($productData['name']);
$_product->setTypeId('simple');
$_product->setAttributeSetId(4);
$_product->setCategoryIds($this->getCategoryId($productData['category']));
$_product->setSku($productData['sku']);
$_product->setStatus(2);
$_product->setUrlKey(strtolower($urlKey) . '-' . $productData['sku']);
$_product->setWebsiteIds(array(1));
$_product->setVisibility(4);
$_product->setDescription($productData['description']);
$_product->setShortDescription($productData['short_description']);
$_product->setPrice($productData['price']);
if (isset($productData['special_price'])) {
    $_product->setSpecialPrice($productData['special_price']);
    $_product->setSpecialFromDate(''); //special price from (MM-DD-YYYY)
    $_product->setSpecialToDate(''); //special price to (MM-DD-YYYY)
}
$_product->setMetaTitle($productData['meta_title']);
$_product->setMetaKeyword($productData['meta_keyword']);
if (!empty($productData['tier_price'])) {
    $_product->setTierPrices($productData['tier_price']);
}
$_product->setWeight($productData['weight']);
$_product->setMetaDescription($productData['meta_description']);
$_product->setTaxClassId($productData['tax_class_id']);
$shoeColorId = $this->_eavAttribute->getIdByCode('catalog_product', 'color');
$shoeBrandId = $this->_eavAttribute->getIdByCode('catalog_product', 'manufacturer');
$_product->setColor($this->getAttributeOptionId($productData['color'], $shoeColorId, 'color'));
$_product->setManufacturer($this->getAttributeOptionId($productData['manufacturer'], $shoeBrandId, 'manufacturer'));
$_product->setStockData(
    array(
        'use_config_manage_stock' => 0, //'Use config settings' checkbox
        'manage_stock' => 1, //manage stock
        'is_in_stock' => $productData['is_in_stock'], //Stock Availability
        'qty' => $productData['stock'], //qty
    )
);
$_product->save();

The issue with code is missing inventory source details, I am looking for a way to create product programmatically and assigning the source at the same time.

How can I create product programmatically with proper inventory management?

Best Answer

Can you please set stock data this way in Magento 2.3

Also please inject product and productRepository like following

$_product->setStockData(
     [
        'use_config_manage_stock' => 0,
        'qty' => $productData['stock'],
        'is_qty_decimal' => 0,
        'manage_stock' => 1,
        'is_in_stock' => $productData['is_in_stock']
     ]
    );

UPDATE

I have tried this way and its working fine for me, Check this screenshot for more information : https://prnt.sc/me62gf and this https://prnt.sc/me637c

Check my controller below.

namespace Vendor\Module\Block\Index;

class Index extends \Magento\Framework\View\Element\Template
{

    protected $_productFactory;

    /**
     * Constructor
     *
     * @param \Magento\Framework\View\Element\Template\Context  $context
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Catalog\Model\ProductFactory $productFactory,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->_productFactory = $productFactory;
    }

    public function FunctionName()
    {
        $_product = $this->_productFactory->create();

        $mainImage = "";
        $imagesToImport = "";

        $urlKey = $this->geturlKey('url_key');
        $_product->setName('name');
        $_product->setTypeId('simple');
        $_product->setAttributeSetId(4);
        $_product->setCategoryIds([]);
        $_product->setSku('psku');
        $_product->setStatus(2);
        $_product->setUrlKey('url_key');
        $_product->setWebsiteIds([1]);
        $_product->setVisibility(4);
        $_product->setDescription('description');
        $_product->setShortDescription('short_description');
        $_product->setPrice(30.3);
        //if (isset($productData['special_price'])) {
            $_product->setSpecialPrice(20.6);
            $_product->setSpecialFromDate(''); //special price from (MM-DD-YYYY)
            $_product->setSpecialToDate(''); //special price to (MM-DD-YYYY)
        //}
        $_product->setMetaTitle('meta_title');
        $_product->setMetaKeyword('meta_keyword');

        $_product->setWeight('1.0');
        $_product->setMetaDescription('meta_description');

        $_product->setColor('color');
        $_product->setManufacturer('manufacturer');
        $_product->setStockData(
            [
                'use_config_manage_stock' => 0, //'Use config settings' checkbox
                'manage_stock' => 1, //manage stock
                'is_in_stock' => 1, //Stock Availability
                'qty' => 100, //qty
            ]
        );
        //echo "<pre>";print_r($_product->debug()); exit();
        $_product->save();
    }
}