3
votes

I am using shopping cart price rules in my custom module, every thing is working fine I just want to get product ids against every rule. If there are 10 products in cart and on 3 of them had some rules applied, rule #1 on 2 products and rule #2 on 1 product. How can I mark the products ids against every rule?

2

2 Answers

2
votes

Just change process function in Validator.php to

public function process($_quote) {
    $i               = 0;
    $quote           = $_quote;
    $customerSession = Mage::getSingleton('customer/session');
    foreach ($this->_rules as $rule) {
        // already tried to validate and failed
        if ($rule->getIsValid() === false) {
            continue;
        }
        if ($rule->getIsValid() !== true) { 
            $rule->afterLoad();
            if (!$rule->validate($quote)) { // quote does not meet rule's conditions , //Call Found.php
                $rule->setIsValid(false);
                continue;
            }
            $rule->setIsValid(true); // passed all validations, remember to be valid
        }

        $this->_appliedProductsIds[]                 =  Mage::getSingleton('checkout/session')->getReturnProductRuleValues();
        $this->_appliedProductsIds[$i]['program_id'] =  $rule->getProgramId();
        Mage::getSingleton('checkout/session')->unsReturnProductRuleValues($this->_ReturnValues);
        $i = $i + 1;
    }
    return $this;
}

And validate function in Found.php to

public function validate(Varien_Object $object) { 
//Called form Validator.php
    $all       = $this->getAggregator() === 'all';
    $true      = (bool)$this->getValue();
    $found     = false;

$Count =  count($object->getAllItems()); 
$i = 0;
    foreach ($object->getAllItems() as $item) {
        $found = $all ? true : false;
        foreach ($this->getConditions() as $cond) {

            $validated = $cond->validate($item); // Call to Product.php's function 'validate'

    if($validated) {
        $this->_ProductId[] = $item->getProductId();
    }

    if($i == $Count) {
        if ($all && !$validated) {
        $found = false;
        break;
        } elseif (!$all && $validated) {
        $found = true;
        break 2;
        }
    }

        }
    if($i == $Count) {
    if ($found && $true) {
        break;
    }
    }
    $i = $i + 1;
    }

$this->_ReturnValues['Product_Id'] = $this->_ProductId;
if(!empty($this->_ProductId)) {
    $this->_ReturnValues['Bool'] = true;
} else {
    $this->_ReturnValues['Bool'] = false;
}

    if ($found && $true) {
        // found an item and we're looking for existing one
    Mage::getSingleton('checkout/session')->setReturnProductRuleValues($this->_ReturnValues);
        return true;
    } elseif (!$found && !$true) {
        // not found and we're making sure it doesn't exist
    Mage::getSingleton('checkout/session')->setReturnProductRuleValues($this->_ReturnValues);
        return true;
    }
Mage::getSingleton('checkout/session')->setReturnProductRuleValues($this->_ReturnValues);
    return false;
}

And access the values in Observer with Vadidator class object like

$validator = Mage::getModel('modulename/validator')
               ->init($customer->getWebsiteId(), $customerGroupId);

$v                   = $validator->process($quote);
$_appliedProductsIds = $v->_appliedProductsIds;

Hop this will help someone..

-2
votes

I think the following function will help you:

Load a specific rule and then use the following function to get the affected products:

$rule->getMatchingProductIds()

public function getSpecialPriceProducts()
{
        $categoryID = $this->getCategoryId();
        if($categoryID)
        {
          $category = new Mage_Catalog_Model_Category();
          $category->load($categoryID); // this is category id
          $collection = $category->getProductCollection();
        } else
        {
          $collection = Mage::getResourceModel('catalog/product_collection');
        }

        $todayDate = date('m/d/y');
        $tomorrow = mktime(0, 0, 0, date('m'), date('d'), date('y'));
        $tomorrowDate = date('m/d/y', $tomorrow);

        Mage::getModel('catalog/layer')->prepareProductCollection($collection);
        $collection->addAttributeToSort('created_at', 'desc');
        $collection->addStoreFilter()
                ->addAttributeToSelect(array('name', 'price', 'short_description','image','small_image','url_key'), 'inner');
        $collection->addAttributeToFilter('special_price', array('gt' => 0));
        $collection->addAttributeToFilter('special_to_date', array('date' => true, 'to' => $todayDate))
            ->addAttributeToFilter('special_from_date', array('or'=> array(
            0 => array('date' => true, 'from' => $tomorrowDate),
            1 => array('is' => new Zend_Db_Expr('null')))
            ), 'left');

        $rules = Mage::getResourceModel('catalogrule/rule_collection')->load();

        // 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 = Mage::getModel('catalog/product')->getCollection()
                ->addAttributeToSelect(array('name', 'price', 'short_description','image','small_image','url_key'), 'inner')
                ->addAttributeToFilter('entity_id',array('in'=>$arr))
                ->load();
        }
        return $collection;
}