1

I had a problem where product import files with only sku and qty fields were importing the wrong qty's for most items. I realized that whatever qty the first item had would be applied to all the rest of the items.

I managed to fix it. I'm not sure if it's actually a bug or may be caused by some extension I am using, but I thought I would report it here and see if anyone has heard of this.

I located the problem in class Mage_ImportExport_Model_Import_Entity_Product extends Mage_ImportExport_Model_Import_Entity_Abstract protected function _saveStockItem().

It appears that the $row variable is created with this line in loop 1:

$row['product_id'] = $this->_newSku[$rowData[self::COL_SKU]]['entity_id'];

But on the next loop, the $row variable is not reset and retains data from the previous item.

Here is the part of the function I am looking at:

while ($bunch = $this->_dataSourceModel->getNextBunch()) {
        $stockData = array();

        // Format bunch to stock data rows
        foreach ($bunch as $rowNum => $rowData) {
            if (!$this->isRowAllowedToImport($rowData, $rowNum)) {
                continue;
            }
            // only SCOPE_DEFAULT can contain stock data
            if (self::SCOPE_DEFAULT != $this->getRowScope($rowData)) {
                continue;
            }
            $row = array(); // ADDED THIS LINE TO FIX POSSIBLE BUG
            $row['product_id'] = $this->_newSku[$rowData[self::COL_SKU]]['entity_id'];
            $row['stock_id'] = 1;

            /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */
            $stockItem = Mage::getModel('cataloginventory/stock_item');
            $stockItem->loadByProduct($row['product_id']);
            $existStockData = $stockItem->getData();

            }
            $row = array_merge(
                $defaultStockData,
                array_intersect_key($existStockData, $defaultStockData),
                array_intersect_key($rowData, $defaultStockData),
                $row
            );
            $stockItem->setData($row);
            // ETC...
            // ...
            // ...
        }
}

Below is the same section of code from Magento 1.5. It also does not reset the variable using $row = array(), but for some reason it avoids the problem it's having in 1.7:

while ($bunch = $this->_dataSourceModel->getNextBunch()) {
        $stockData = array();

        foreach ($bunch as $rowNum => $rowData) {
            if (!$this->isRowAllowedToImport($rowData, $rowNum)) {
                continue;
            }
            // only SCOPE_DEFAULT can contain stock data
            if (self::SCOPE_DEFAULT == $this->getRowScope($rowData)) {
                $row = array_merge(
                    $defaultStockData,
                    array_intersect_key($rowData, $defaultStockData)
                );
                $row['product_id'] = $this->_newSku[$rowData[self::COL_SKU]]['entity_id'];
                $row['stock_id'] = 1;
                /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */
                $stockItem = Mage::getModel('cataloginventory/stock_item', $row);

                if ($helper->isQty($this->_newSku[$rowData[self::COL_SKU]]['type_id'])) {
                    if ($stockItem->verifyNotification()) {
                        $stockItem->setLowStockDate(Mage::app()->getLocale()
                            ->date(null, null, null, false)
                            ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT)
                        );
                    }
                    $stockItem->setStockStatusChangedAutomatically((int) !$stockItem->verifyStock());
                } else {
                    $stockItem->setQty(0);
                }
                $stockData[] = $stockItem->getData();
2

You are right, it's a bug.

Replace the following lines:

$row = array_merge(
    $defaultStockData,
    array_intersect_key($existStockData, $defaultStockData),
    array_intersect_key($rowData, $defaultStockData),
    $row
);

with

$row = array_merge(
    $row,
    $defaultStockData,
    array_intersect_key($existStockData, $defaultStockData),
    array_intersect_key($rowData, $defaultStockData)
);

in app/code/core/Mage/ImportExport/Model/Import/Entity/Product.php. Of course, you should do a rewrite and not modify the core file directly as the change would be gone with the next update.

  • Hi Andreas. It seems you are using the fact that array_merge's later arguments overwrite earlier arguments with the same keys, such that earlier arguments can act as "defaults". So it makes sense to put $row first. Is your solution better than my idea to reset $row to $row = array()? – Buttle Butkus Feb 15 '15 at 8:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.