magento2-connector-community icon indicating copy to clipboard operation
magento2-connector-community copied to clipboard

Categories matched by rule are not handled at all

Open bartoszkubicki opened this issue 1 year ago • 3 comments

Environment and configuration

  1. 100.4.16 - but haven't found fixes or handling for given issue in changelog

Steps to reproduce

  1. Configure categories matched rule (by attribute for example) image
  2. Have corresponding categories in akeneo (empty)
  3. Import products
  4. Check if products are correctly assigned to categories

Expected result

  1. Products are assigned according to rules

Actual result

  1. Categories that matches products by rules are wiped out or products count is lower (if we exclude some families from import)

Issue was solved by out team with following plugin:

use Akeneo\Connector\Job\Product;
use Exception;
use Magento\Catalog\Model\Category;
use Magento\Catalog\Model\ResourceModel\Category as CategoryResource;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\VisualMerchandiser\Model\Category\Builder;
use Magento\VisualMerchandiser\Model\ResourceModel\Rules\Collection as RulesCollection;
use Magento\VisualMerchandiser\Model\ResourceModel\Rules\CollectionFactory as RulesCollectionFactory;

class RebuildDynamicCategories
{
    private CategoryResource $categoryResource;
    private CategoryCollectionFactory $categoryCollectionFactory;
    private Builder $builder;
    private RulesCollectionFactory $rulesCollectionFactory;

    public function __construct(
        CategoryResource $categoryResource,
        CategoryCollectionFactory $categoryCollectionFactory,
        Builder $builder,
        RulesCollectionFactory $rulesCollectionFactory
    ) {
        $this->categoryResource = $categoryResource;
        $this->categoryCollectionFactory = $categoryCollectionFactory;
        $this->builder = $builder;
        $this->rulesCollectionFactory = $rulesCollectionFactory;
    }

    public function afterSetCategories(Product $subject, $result)
    {
        $this->rebuildDynamicCategories($subject);
        return $result;
    }

    private function rebuildDynamicCategories(Product $productImport): void
    {
        $rulesCollection = $this->rulesCollectionFactory->create();
        /** @var $rulesCollection RulesCollection */
        $rulesCollection->addFieldToFilter('is_active', ['eq' => 1]);
        $categoriesIds = $rulesCollection->getColumnValues('category_id');

        $categoryCollection = $this->categoryCollectionFactory->create();
        $categoryCollection->addAttributeToSelect('*')
            ->addFieldToFilter($this->categoryResource->getEntityIdField(), ['in' => $categoriesIds]);

        foreach ($categoryCollection as $category) {
            $this->builder->rebuildCategory($category);
            $this->saveRebuiltCategory($productImport, $category);
        }
    }

    private function saveRebuiltCategory(Product $productImport, Category $category): void
    {
        try {
            $this->categoryResource->save($category);
        } catch (Exception $exception) {
            $productImport->setAdditionalMessage(
                __(
                    'Dynamic category %1 (ID: %2) couldn\'t be rebuilt correctly',
                    $category->getName(),
                    $category->getId()
                )
            );
        }
    }
}

bartoszkubicki avatar Mar 28 '23 15:03 bartoszkubicki

@bartoszkubicki we have the same issue. Could you team make a pull request so this could hopefully end up in a future release?

oefterdal avatar Oct 03 '23 07:10 oefterdal

@magentix I can see a proposal of my fix for the given issue has been added. Unfortunately, I can see you have removed two dependencies from the constructor method and you are pulling them from the object manager. This is a clear antipattern and I have no idea why you did that. Please fix it or remove my name from that class. I don't want to be linked with such poor-quality code.

bartoszkubicki avatar Mar 04 '24 14:03 bartoszkubicki

@bartoszkubicki

We must be compatible with all Magento versions, the use of VisualMerchandiser classes in the constructor breaks all Magento OpenSource / OpenMage and Adobe Commerce without the module.

Note that the plugin was removed in 104.0.7 (the product sort order is not persisted with this technique).

https://github.com/akeneo/magento2-connector-community/commit/34f65b7aecb2b22c66bbc6c67d5a02542c7ccf3e

magentix avatar Mar 04 '24 14:03 magentix