As known in Magento there are multiple ways to apply special pricing from products and based on many answers I found this forum I created a module with Layer Navigation to load all products that have special prices applied and also Catalog rule price applied however it ended up loading a couple of products and not all products.
<?php
namespace VendorSpecialModel;
use MagentoCatalogApiCategoryRepositoryInterface;
use MagentoCatalogModelResourceModelProductAttributeCollectionFactory as AttributeCollectionFactory;
use MagentoCatalogModelResourceModelProductCollectionFactory;
use MagentoCatalogRuleModelResourceModelRuleCollectionFactory as RuleCollectionFactory;
use MagentoCatalogModelProduct;
/**
* Vendor Special Layer model class
*/
class Layer extends MagentoCatalogModelLayer
{
/**
* @var CollectionFactory
*/
protected $productCollectionFactory;
/**
* @var RuleCollectionFactory
*/
protected $ruleCollectionFactory;
/**
* @var MagentoCatalogModelProduct
*/
protected $_modelProduct;
/**
* Layer constructor.
* @param MagentoCatalogModelLayerContextInterface $context
* @param MagentoCatalogModelLayerStateFactory $layerStateFactory
* @param AttributeCollectionFactory $attributeCollectionFactory
* @param MagentoCatalogModelResourceModelProduct $catalogProduct
* @param MagentoStoreModelStoreManagerInterface $storeManager
* @param MagentoFrameworkRegistry $registry
* @param CategoryRepositoryInterface $categoryRepository
* @param CollectionFactory $productCollectionFactory
* @param RuleCollectionFactory $ruleCollectionFactory
* @param Product $product
* @param array $data
*/
public function __construct(
MagentoCatalogModelLayerContextInterface $context,
MagentoCatalogModelLayerStateFactory $layerStateFactory,
AttributeCollectionFactory $attributeCollectionFactory,
MagentoCatalogModelResourceModelProduct $catalogProduct,
MagentoStoreModelStoreManagerInterface $storeManager,
MagentoFrameworkRegistry $registry,
CategoryRepositoryInterface $categoryRepository,
CollectionFactory $productCollectionFactory,
RuleCollectionFactory $ruleCollectionFactory,
Product $modelProduct,
array $data = []
) {
$this->productCollectionFactory = $productCollectionFactory;
$this->ruleCollectionFactory = $ruleCollectionFactory;
$this->_modelProduct = $modelProduct;
parent::__construct(
$context,
$layerStateFactory,
$attributeCollectionFactory,
$catalogProduct,
$storeManager,
$registry,
$categoryRepository,
$data
);
}
/**
* Get special product collection
* @return MagentoCatalogModelResourceModelProductCollection
* @throws Zend_Date_Exception
*/
public function getProductCollection()
{
if (isset($this->_productCollections['vendor_custom'])) {
$collection = $this->_productCollections['vendor_custom'];
} else {
$date = new Zend_Date();
$collection = $this->productCollectionFactory->create()
->addAttributeToSelect('*')
->addAttributeToFilter(
'special_from_date',
[
'or' => [
0 => [
'date' => true,
'to' => $date->get('YYYY-MM-dd') . ' 23:59:59'
],
1 => [
'is' => new Zend_Db_Expr('null')
],
]
],
'left'
)
->addAttributeToFilter(
'special_to_date',
[
'or' => [
0 => [
'date' => true,
'from' => $date->get('YYYY-MM-dd') . ' 00:00:00'
],
1 => [
'is' => new Zend_Db_Expr('null')
],
]
],
'left'
)
->addAttributeToFilter('special_price',array('lt'=>new Zend_Db_Expr("price_index.price")));
$this->prepareProductCollection($collection);
// $collection->addAttributeToFilter('special',MagentoCatalogModelProductAttributeSourceStatus::STATUS_ENABLED);
$rules = $this->ruleCollectionFactory->create();
// read: if there are active rules
if($rules->getData()) {
$rule_ids = array(); // i used this down below to style the products according to which rule affected
$productIds[] = array(); // this will hold the ids of the products
foreach($rules as $rule) {
$rule_ids[] = $rule->getId();
$productIds = $rule->getMatchingProductIds(); // affected products come in here
}
// merge the collections: $arr is an array and keeps all product IDs we fetched before with the special-price-stuff
$arr = $collection->getAllIds();
if($productIds) {
// if there are products affected by catalog price rules, $arr now also keeps their IDs
$arr = array_merge($arr,$productIds);
}
// we initialize a new collection and filter solely by the product IDs we got before, read: select all products with their entity_id in $arr
$collection = $this->_modelProduct->getCollection()->addAttributeToFilter('entity_id',array('in'=>$arr))
->load();
}
$this->_productCollections['vendor_custom'] = $collection;
}
return $collection;
}
}
I have more than 4 rules that runs discount on prices and also more than 100 products that include special pricing some with date define and others not. The total products should be 500+ products between direct special_price
attribute and catalog_rule
collection.
How’s it possible to combine all those products and load them properly in a dedicated page named “Special Offers”