Magento – Magento 2 API – Get list of products with Catalog Price Rule

apicatalog-price-rulesmagento2product-list

We are using Magento 2.1.7 and building some API endpoints to serve our need.

Following is how we get Products list and send them as json from API call.

<?php
namespace Vendor\Customer\Model;

use Magento\Framework\Api\Filter;

class ProductRepository
{
    protected $_productCollection, $productRepository, $searchCriteriaBuilder;

    public function __construct(
        \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder
    )
    {
        $this->productRepository = $productRepository;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
    }

    /**
    * @return \Magento\Catalog\Api\Data\ProductSearchResultsInterface
    */
    public function getProductCollection()
    {
        $searchCriteria = $this->searchCriteriaBuilder->create();

        $this->_productCollection = $this->productRepository->getList($searchCriteria);

        return $this->_productCollection;
    }
}

We need to know if we can add some search criteria to getProductCollection() method using Filter to get only those products associated to some active catalog price rule with discounted price.

Or if we have any other method to get Products with Catalog Price Rule and discounted Price, guide me in that direction.

Best Answer

When you create a catalog price rule, Magento creates some entries in catalogrule_product table. You can see which products are affected by the price rules created.

Unfortunately ProductRepository does not allow you to filter by catalog price rule. However, you can modify this class by extending it.

The only thing you need to add is the following line.

$collection->joinTable('catalogrule_product', 'product_id=entity_id', ['product_id'], null, 'inner');

Let's say create MyProductRepository as follows:

class MyProductRepository extends \Magento\Catalog\Model\ProductRepository
{
    public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria)
    {
        /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
        $collection = $this->collectionFactory->create();
        $this->extensionAttributesJoinProcessor->process($collection);

        foreach ($this->metadataService->getList($this->searchCriteriaBuilder->create())->getItems() as $metadata) {
            $collection->addAttributeToSelect($metadata->getAttributeCode());
        }
        $collection->joinTable('catalogrule_product','product_id=entity_id', ['product_id'],null, 'inner');
        $collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner');
        $collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');

        //Add filters from root filter group to the collection
        foreach ($searchCriteria->getFilterGroups() as $group) {
            $this->addFilterGroupToCollection($group, $collection);
        }
        /** @var SortOrder $sortOrder */
        foreach ((array)$searchCriteria->getSortOrders() as $sortOrder) {
            $field = $sortOrder->getField();
            $collection->addOrder(
                $field,
                ($sortOrder->getDirection() == SortOrder::SORT_ASC) ? 'ASC' : 'DESC'
            );
        }
        $collection->setCurPage($searchCriteria->getCurrentPage());
        $collection->setPageSize($searchCriteria->getPageSize());
        $collection->load();

        $searchResult = $this->searchResultsFactory->create();
        $searchResult->setSearchCriteria($searchCriteria);
        $searchResult->setItems($collection->getItems());
        $searchResult->setTotalCount($collection->getSize());
        return $searchResult;
    }
}

Be careful, you cannot use \Magento\Catalog\Api\ProductRepositoryInterface anymore. You have to call your implementation.

$productRepository = $objectManager->get(\MyVendor\MyModule\Model\MyProductRepository::class);
Related Topic