How to programmatically apply a magento sales rule to an quote item

12,839

Solution 1

unfortunately Chuck isn't currently doing consulting work. So I had to dig deeper into the entangled magento discount calculation.

The recalculation by totals_collected_flag is IMHO no options, as it triggers tax calculation twice, which means the quote totals get totally wrong.

I had success to populate my own discount type by implementing a new Mage_Sales_Model_Quote_Address_Total_Abstract. This one is using in it's collect()-method a slightly customized version of Mage_SalesRule_Model_Validator which loads custom sales rules according to my discount strategy.

The custom class is included into the Magento totals calculation by adding the following XML to the modules config.

<global>
    ... 
    <sales>
        <quote>
           <totals>
               <requestquotation_discount>
                   <class>requestquotation/request_discount</class>
                   <after>discount</after>
                   <before>grand_total</before>
               </requestquotation_discount>
           </totals>
        </quote>
    </sales>
</global>

In the implementation the "code" of the totals-calculator is set to "discount" and no previous calculated discount is reset. With this method, the custom discount can run side by side with Magento's default discount system as well it doesn't interfere with tax-calculation, etc.

Hope, this helps somebody struggling with the same problems.

Solution 2

Chuck Norris is the only one who has Magento documentation. But never the less you could try to set the collected flag to false prior calling collectTotals():

$quote->setTotalsCollectedFlag(false)->collectTotals();

and optionally if you end up with wrong totals after calling collectTotals more than once within same object instance then you need to be aware of following issue:

http://www.magentocommerce.com/bug-tracking/issue?issue=11893

Share:
12,839
Joachim Rosskopf
Author by

Joachim Rosskopf

Updated on June 17, 2022

Comments

  • Joachim Rosskopf
    Joachim Rosskopf almost 2 years

    I'm currently implementing a plugin to manage quotation requests in a magento shop system. The idea is, that the request is associated with an quote and somebody in the backend should be able to apply individual sales rules per quote item.

    There was no problem to implement the functionality to create and edit the involved entities on the frontend as well in backend. But I'm unable to apply a certain sales-rule to a quote item and have that rule reflected in the row total as well as the subtotal of the quote.

    My current approach is to use the sales_quote_address_discount_item-Hook. There I use an instance of a class derived from Mage_SalesRule_Model_Validator which overloaded _getRules()-Method gives the relevant Mage_SalesRule_Model_Rules. The relevant code of the event-observer looks like:

    $quote_item = $event->getItem();
    
    $request_item = $this->helper->getRequestItemByQuoteItemId($quote_item->getItemId());
    if (! $this->isRelevantRequestItem($request_item))
        return $this;
    
    $validator = Mage::getModel("requestquotation/request_validator")
                     ->addRule($request_item->getRule());
    $validator->process($quote_item);
    

    When I step with the debugger through process()-Method, my supplied rule works and is applied to the quote item. But any further collectTotals()on the quote and an $quote_item->save() has no effects on the of row-totals and the subtotal of the quote.

    Is there any documentation or example how to add an sales-rule (better in my opinion as it is traceable) or an discount manually, programatically to an quote-item and/or to the quote itself.

    Thank you in advance and best regards!

    Joachim

  • Anton S
    Anton S over 12 years
    The recalculation by totals_collected_flag is IMHO no options, as it triggers tax calculation twice, which means the quote totals get totally wrong. this is a simple bug to solve, collectTotals will cache prices of quote items in their objects and thus failing to calculate twice all you have to do is to reset the cached values as well before calling it twice. But +1 for fixing teeth through asshole as this shows the talent :)
  • Anton S
    Anton S over 12 years
    i created a ticket in magneto bug-list for this issue as well magentocommerce.com/bug-tracking/issue?issue=11893
  • Joachim Rosskopf
    Joachim Rosskopf over 12 years
    Thank you for filing a bug report. I shared the above solution not only as an workaround for the discount-calculation bug. But with the above mentioned method you can add some custom logic to the totals calculation in a clean and non interfering way.
  • Anton S
    Anton S over 12 years
    its just a joke :) but sure implementing your own totals object is right approach