magento-engcom / import-export-improvements

Open Software License 3.0
31 stars 29 forks source link

[MAGETWO-2975] Import of products erases product order in category setting #25

Open piotrekkaminski opened 7 years ago

piotrekkaminski commented 7 years ago

From @piotrekkaminski on November 2, 2017 21:17

Setting product position setting, exporting products, and reimporting products causes product position setting to be erased.

Preconditions

  1. Version 2.0

STEPS TO REPRODUCE

1) Sign into admin panel 2) Create 4 test products 3) Add them all to test category 4) Go to Category settings and set positions for all 4 products 5) Export file 6) Look over exported CSV file - no column showing for category position 7) Import file - replace data 8) Look at category settings - note product order is erased

Actual results

Random: 2 of the positions stay but one of them gets changed (See attached trunk category position settings after.png and trunk category position settings before.png). trunk category position settings before trunk category position settings after

EXPECTED RESULTS:

Positions for products in categories should be retained from before import to after export.

Copied from original issue: magento/magento2#11981

VasylShvorak commented 6 years ago

@dmanners , I was able to reproduce this issue on ver. 2.3.0-dev.

Rickertje commented 6 years ago

Can anyone tell me why this was closed?

dmanners commented 6 years ago

Oh thanks for catching this @Rickertje this was closed due to human error on my part :( I will reopen it now.

brosenberger commented 6 years ago

following class can be altered to ensure positions do not get lost on import: \Magento\CatalogImportExport\Model\Import\Product

replacement within di.xml: <preference for="Magento\CatalogImportExport\Model\Import\Product" type="Vendor\Module\Model\Import\Product" />

The problematic function is _saveProductCategories where the position is manually set to 1 instead of the preset values from the backend. All relations are gonna be reinserted with the wrongly set position.

This could be fixed with following adaption of the method (preloading of position values if they exist) and reseting them into the inserOnDuplicate array: `protected function _saveProductCategories(array $categoriesData) { static $tableName = null;

    if (!$tableName) {
        $tableName = $this->_resourceFactory->create()->getProductCategoryTable();
    }
    if ($categoriesData) {
        $categoriesIn = [];
        $delProductId = [];

        $positionsData = [];
        foreach ($this->fetchCategoryProductPositions($tableName, $categoriesData) as $relation) {
            $positionsData[$relation['product_id'].'__##__'.$relation['category_id']] = intval($relation['position']);
        }

        foreach ($categoriesData as $delSku => $categories) {
            $productId = $this->skuProcessor->getNewSku($delSku)['entity_id'];
            $delProductId[] = $productId;

            foreach (array_keys($categories) as $categoryId) {
                $position = isset($positionsData[$productId.'__##__'.$categoryId])?$positionsData[$productId.'__##__'.$categoryId] :1;
                $categoriesIn[] = ['product_id' => $productId, 'category_id' => $categoryId, 'position' => $position];
            }
        }
        if (Import::BEHAVIOR_APPEND != $this->getBehavior()) {
            $this->_connection->delete(
                $tableName,
                $this->_connection->quoteInto('product_id IN (?)', $delProductId)
            );
        }
        if ($categoriesIn) {
            $this->_connection->insertOnDuplicate($tableName, $categoriesIn, ['product_id', 'category_id']);
        }
    }
    return $this;
}

protected function fetchCategoryProductPositions($tableName, $categoriesData) {
    return $this->_connection->fetchAll($this->_connection->select()
        ->from($tableName, ['product_id', 'category_id', 'position'])
        ->where('product_id IN (?)', array_map(function ($sku) {
            return $this->skuProcessor->getNewSku($sku);
        }, array_keys($categoriesData))));
}`