Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

php

magento

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

like image 736
Joachim Rosskopf Avatar asked May 10 '11 04:05

Joachim Rosskopf


2 Answers

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

like image 88
Anton S Avatar answered Sep 21 '22 10:09

Anton S


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.

like image 39
Joachim Rosskopf Avatar answered Sep 18 '22 10:09

Joachim Rosskopf