Magento - get price rules from order
does anyone know how one can get the catalog- and cart price rules from an order?
I know that I can get the discount percentage from an order item via the method getDiscountPercent()
, but how can I get all the rules that were applied to the whole order?
For example, I have a rule "Customer Group X gets 20% off all items in the store".
Now I want to determine which rules were开发者_如何学运维 actually applied when the order has been submitted by the user. I need this for an order export interface where I have to supply all discounts that the user got.
Thanks in advance!
Have a look in the sales_flat_order_item
table. there is a field called applied_rule_ids
which will give you the id of the rule applied to that item. Also you can find out in this table how much discount was applied and the percentage.
Example
//The order I want to check
$order_id = 859;
//Get the list of items for your order
$items = Mage::getModel('sales/order_item')
->getCollection()
->addFilter('order_id',array('eq'=>$order_id));
//loop through each item
foreach($items as $item){
//if the item has not had a rule applied to it skip it
if($item->getAppliedRuleIds() == '')continue;
/*
* I cant remember in the database they might be comma separated or space if multiple rules were applied
* the getAppliedRuleIds() function is the one you want
*/
foreach(explode(",",$item->getAppliedRuleIds()) as $ruleID){
//Load the rule object
$rule = Mage::getModel('catalogrule/rule')->load($ruleID);
// Throw out some information like the rule name what product it was applied to
echo "<p>".$item->getSku()." had rule ".$rule->getName()."(".$item->getAppliedRuleIds().") applied </p>";
}
}
/* Example of getting catalog rules applied for specific product */
$productId = 6;
$user = Mage::getSingleton('customer/session')->getCustomer();
$product = Mage::getModel('catalog/product')->load($productId);
$storeId = $product->getStoreId();
$websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
$dateTs = Mage::app()->getLocale()->storeTimeStamp($storeId);
$customerGroupId = $user->getGroupId();
$resource = Mage::getResourceModel('catalogrule/rule');
$rules = $resource->getRulesFromProduct($dateTs, $websiteId, $customerGroupId, $productId);
Yeah, it's kind of a pain that Magento doesn't leave any history around in the order record when you use sale pricing with regard to how that base price was calculated.
Fortunately it's open source, so you can patch this in if you like.
I recently wrote an observer that fires when the order record is loaded, to address this very issue. It cross-references the line base_price
with the product's current full-retail price. If there is a mismatch, it adds a couple fields to the order item to help expose this info to any external script that's listening (in our case, a custom order fulfillment script that relays orders to SAP using Magento's SOAP API).
Here's the basic idea - make a module in app/code/local/YourCo/SalePricing
and set up an observer class in app/code/local/YourCo/SalePricing/Model/Promo/Observer.php
<?php
class YourCo_SalePricing_Model_Promo_Observer
{
public function __construct()
{
}
// tag order items that have a sale-price
// with original retail price and total sale discount for this line
public function report_sale_pricing($observer)
{
$event = $observer->getEvent();
$order = $event->getOrder();
$items = $order->getAllItems();
foreach ($items as $item) {
// heads up, you may want to do this for other types as well...
if ($item->getProductType() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
$regular_price = $this->_lookupFullRetail($item,$order->getStoreId());
$sale_price = $item->getBasePrice();
if ($regular_price - $sale_price > 0.005) {
$qty = $item->getQtyOrdered();
$total_sale_discount = ($regular_price * $qty) - ($sale_price * $qty);
$item->setFullRetailPrice((string)$regular_price);
$item->setSaleDiscount((string)$total_sale_discount);
}
}
}
}
private function _lookupFullRetail(&$item,$store_id)
{
$mpid = $item->getProductId();
$p = Mage::getModel('catalog/product')->setStoreId($store_id)->load($mpid);
return $p->getPrice();
}
}
Your module's etc/config.xml
needs to tell magento when to run your observer:
<?xml version="1.0"?>
<config>
<global>
<models>
<yourco_salepricing>
<class>YourCo_SalePricing_Model</class>
</yourco_salepricing>
</models>
<events>
<sales_order_load_after>
<observers>
<yourco_salepricing>
<type>singleton</type>
<class>YourCo_SalePricing_Model_Promo_Observer</class>
<method>report_sale_pricing</method>
</yourco_salepricing>
</observers>
</sales_order_load_after>
</events>
</global>
</config>
Make sure to activate your new module in app/etc/modules/...
and clear the config cache.
Now, when you load the order, you can loop over each item and check for $item->getFullRetailPrice() --
if it's there, you know the item was on sale (well, either that or the price has gone up since the order was placed). You still don't know why, ie which sale price rule was in force, but for our application we didn't really care, and getting that info to be saved with the order would have been a much tougher mod.
What might help you though:
$order = Mage::getModel('sales/order')->load(20569);
echo Mage::helper('sales')->__('Discount (%s)', $order->getDiscountDescription());
This prints out all the discount rules name which have been applied to the order.
精彩评论