Magento - Modify Shopping Cart Rules Function to apply discounts by Percentage of Original Price Instead of Product Price Discount - magento

I'm working on a project where the entire store products have a special price different (lowered) from the original price.
I want to be able to apply shopping cart discounts By Percentage of the Original Price just like Catalog Discount Price Rules does.
Right now, if I apply a shopping cart “Percentage of product price discount” rule, it will apply the discount to the special price instead of the original price.
Where is the function for Shopping Cart Rules at? Any details on modifying it to apply discounts on original price will be appreciated.

I recently had to solve the same problem. These two blog guides were very helpful in crafting my final solution.
My custom observer on the salesrule_validator_process event looks like this:
class My_SalesRule_Model_Observer
{
// New SalesRule type
const TO_ORIGINAL_PRICE = 'to_original_price';
/**
* Add the new SalesRule type to the admin form.
* #param Varien_Event_Observer $obs
*/
public function adminhtmlBlockSalesruleActionsPrepareform($obs)
{
$field = $obs->getForm()->getElement('simple_action');
$options = $field->getValues();
$options[] = array(
'value' => self::TO_ORIGINAL_PRICE,
'label' => Mage::helper('salesrule')->__('Percent of original product price discount')
);
$field->setValues($options);
}
/**
* Apply the new SalesRule type to eligible cart items.
* #param Varien_Event_Observer $obs
*/
public function salesruleValidatorProcess($obs)
{
/* #var Mage_SalesRule_Model_Rule $rule */
$rule = $obs->getRule();
if ($rule->getSimpleAction() == self::TO_ORIGINAL_PRICE) {
/* #var Mage_Sales_Model_Quote_Item $item */
$item = $obs->getItem();
// Apply rule qty cap if it exists.
$qty = $rule->getDiscountQty()? min($obs->getQty(), $rule->getDiscountQty()) : $obs->getQty();
// Apply rule stepping if specified.
$step = $rule->getDiscountStep();
if ($step) {
$qty = floor($qty / $step) * $step;
}
// Rule discount amount (assumes %).
$ruleDiscountPercent = $rule->getDiscountAmount();
/* #see My_Catalog_Model_Product::getDiscountPercent */
$productDiscountPercent = $item->getProduct()->getDiscountPercent();
// Ensure that the rule does not clobber a larger discount already present on the $cartItem.
// Do not apply the rule if the discount would be less than the price they were already quoted
// from the catalog (i.e. special_price or Catalog Price Rules).
if ($ruleDiscountPercent > $productDiscountPercent) {
// Reduce $ruleDiscountPercent to just the gap required to reach target pct of original price.
// In this way we add the coupon discount to the existing catalog discount (if any).
$ruleDiscountPercent -= $productDiscountPercent;
$pct = $ruleDiscountPercent / 100;
// Apply the discount to the product original price, not the current quote item price.
$discountAmount = ($item->getProduct()->getPrice() * $pct) * $qty;
$item->setDiscountPercent($ruleDiscountPercent);
$obs->getResult()
->setDiscountAmount($discountAmount)
->setBaseDiscountAmount($discountAmount);
}
}
}
}
If you have set up your extension properly, you should see the new rule type appear under:
Promotions -> Shopping Cart Price Rules -> Edit 'New Rule' -> Actions -> Update prices using the following information: Apply [Percent of original product price discount]
Caveats: you’ll notice I implemented this to work on percentages, including creating a method on the product model to calculate the catalog discounted price (i.e. special price and other discounts applicable at the catalog level). You will need to implement that if you wish to do the same, or update this logic to fit your scenario perhaps just referring to $item->getProduct()->getPrice() instead.

Related

How to filter zero-prices products in listing page

I have used the sorting by ->setOrder('price','desc');
but in this case its not working well when we sort the products by name
Is there any way to sort by price (from lower to bigger) in such way, that products with zero price will bein the end of the list???
public function setCollection($collection)
{
$this->_collection = $collection;
$this->_collection->setCurPage($this->getCurrentPage());
// we need to set pagination only if passed value integer and more that 0
$limit = (int)$this->getLimit();
if ($limit) {
$this->_collection->setPageSize($limit);
}
if ($this->getCurrentOrder()) {
$this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection())
->setOrder('price','desc');
}
return $this;
}
The question not very clear, yet from what I understand:
(Price Sorting) This feature is provided by default in Magento in Product Listing Pages.
Maybe you have changed the price attribute # backend.
Check for price attribute.
Used in Product Listing = Yes
Used for Sorting in Product Listing = Yes
Clear Cache, and you should be ready to go.

magento adding custom parameter and updating price

i want to add custom donate(like tip) module in addition to product price
suppose Product A (price 100) have text box field
1:donate with blank value which user have to enter user can insert any value and product price will be donated value + product price
how can i implement this via observer
i tried using "checkout_cart_product_add_after" observer
code of observer.php
class Mour_Customgroup_Model_Observer
{
public function modifyPrice(Varien_Event_Observer $obs ){
// Get the quote item
$quote = $obs->getEvent()->getQuote();
$item = $obs->getQuoteItem();
$product_id=$item->getProductId();
$_product=Mage::getModel('catalog/product')->load($product_id);
$newprice=$_product->getPrice()+10;
Mage::log('My log entry', null, 'mylogfile.log');
// Set the custom price
$item->setCustomPrice($newprice);
$item->setOriginalCustomPrice($newprice);
// Enable super mode on the product.
$item->getProduct()->setIsSuperMode(true);
}
}
but this code adds same amount to add items in cart
my issue are
how to pass value of donate text box to observer
add donated value to product price

Hide out of stock products only in search result pages

We can easily hide out of stock products in categories and catalog search through : System > Configuration > Catalog > Inventory > Display Out of Stock Products
Yet, how can we hide products only in search results ?
You could override _getSearchableProducts function in class Mage_CatalogSearch_Model_Resource_Fulltext so that it always searches in-stock products.
File to modify: app/code/core/Mage/CatalogSearch/Model/Resource/Fulltext.php
/**
* Retrieve searchable products per store
*
* #param int $storeId
* #param array $staticFields
* #param array|int $productIds
* #param int $lastProductId
* #param int $limit
* #return array
*/
protected function _getSearchableProducts($storeId, array $staticFields, $productIds = null, $lastProductId = 0, $limit = 100)
{
...
->join(
array('stock_status' => $this->getTable('cataloginventory/stock_status')),
$writeAdapter->quoteInto(
'stock_status.product_id=e.entity_id AND stock_status.stock_status = 1 AND stock_status.website_id=?', // add stock_status = 1 condition
$websiteId
),
array('in_stock' => 'stock_status')
);
....
}
Remember to reindex "Catalog Search Index" afterwards.
The above solution using observer also hides the in category. The question is to hide only in search results. so directly adding instock filter product collection results.phtml is appropriate.
i.e Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($productCollection);
correct me if i miss any thing here.
I know a way by which you can achieve this.
Inside Magento/app/design/frontend/rwd/default/template/catalogsearch/result.phtml
$this->getProductListHtml() ;
gives you the desired search result.
Inside list.phtml check this out.
$_productCollection=$this->getLoadedProductCollection();
Magento allows you a way by which you can observe the collection add filters before/after the collection is loaded that is called the Observer way.
Inside the event you observe, try using following particularly for search results:
Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($productCollection);
Hope it helps.

Magento - Promotions don't apply to downloadable files prices

Initial conditions:
Magento 1.7 installed (haven't tried with previous versions)
One (downloadable) product with multiple downloadable files, with prices added to the default product (let's say product that costs 50$ + 2 downloadable files, one free, the other an extra 50$ )
A new promotion (Catalog price rule) that applies to all products (let's say -20%)
More info about promotion:
Applies to all products, all groups, is active and applied, applies 'by percentage of original price', enable discount for subproducts -> Yes, stop further rule for processing -> No
Expected result:
Price for the product with the 50$ file: 80$ (80% from 100$)
Actual result:
Price for the product with the 50$ file: 90$ (80% from the initial 50$, and the full price for the downloadable file).
Conclusion:
The promotion doesn't apply to the extra prices that downloadable files have.
Question(s):
Is this the desired behavior for downloadable files? Or is this a bug ?
Any tips on how to modify the code (eventually create a module) to make it work as expected ? (Just tips, ie. what to extend)
Links / downloadable files its not products entities ( so it doesn't have price_index table and it doesn't treated as products )
There is 2 Ways to apply promotion in products
Catalog Price Rules
Shopping Cart Price Rules
As your question stated that you used Catalog Price Rules I have solved your question using Catalog Price Rules.
Create Module and rewrite the Model
Mage_Downloadable_Model_Product_Type
======
<global>
<models>
<downloadable>
<rewrite>
<product_type>Web_Eproduct_Model_Downloadable_Product_Type</product_type>
</rewrite>
</downloadable>
</models>
</global>
and the Code Below calculate the price of each Link on the fly ( even if you have more than one rule applied to the same product )
class Namespace_Modulename_Model_Downloadable_Product_Type extends Mage_Downloadable_Model_Product_Type {
public function getLinks($product = null)
{
$product = $this->getProduct($product);
$wId = Mage::app()->getWebsite()->getId();
$gId = Mage::getSingleton('customer/session')->getCustomerGroupId();
$catalogRules = Mage::getSingleton('catalogrule/resource_rule')->getRulesFromProduct('',$wId,$gId,$product->getId());
/* #var Mage_Catalog_Model_Product $product */
if (is_null($product->getDownloadableLinks())) {
$_linkCollection = Mage::getModel('downloadable/link')->getCollection()
->addProductToFilter($product->getId())
->addTitleToResult($product->getStoreId())
->addPriceToResult($product->getStore()->getWebsiteId());
$linksCollectionById = array();
foreach ($_linkCollection as $link) {
/* #var Mage_Downloadable_Model_Link $link */
$link->setProduct($product);
$link->setPrice($this->calcLinkPrice($catalogRules,$link->getPrice()));
$linksCollectionById[$link->getId()] = $link;
}
$product->setDownloadableLinks($linksCollectionById);
}
return $product->getDownloadableLinks();
}
public function calcLinkPrice(array $rules = array(),$productPrice = 0 )
{
foreach($rules as $ruleData)
{
$productPrice = Mage::helper('catalogrule')->calcPriceRule(
$ruleData['action_operator'],
$ruleData['action_amount'],
$productPrice);
}
return $productPrice;
}
}
I have tested it and confirmed its working as you expect :)
Try it and let me know your thoughts :)
There is another way to achieve this if you will use Shopping Cart Price Rules i will post it later.
There are 2 types of price rules in Magento, Catalog and Shopping Cart Price Rules. Catalog Rules are enacted on products before they are added to the cart, while Shopping Cart Price Rules are applied in the shopping cart.
You should set this promo as a Shopping Cart Price Rule.

Manual magento order creation - item price original and converted to store currency

I'm using code below to create order in magento:
$quote = Mage::getModel('sales/quote');
$quote->setCheckoutMethod('guest')->save();
$quote->setStore($store);
$quote->setForcedCurrency(Mage::getModel('directory/currency')->load($storeCurrency));
foreach ($productInCardList as $productItem) {
$product = Mage::getModel('catalog/product')->load($productItem['id']);
$product->setPrice($productItem['price']);
$request = new Varien_Object();
$request->setQty($productItem['qty']);
$quote->addProduct($product, $request);
}
$quote->collectTotals();
$quote->reserveOrderId();
$quote->save();
$service = Mage::getModel('sales/service_quote', $quote);
$service->submitAll();
$orderObj = $service->getOrder();
// ... code setting billing, shipping address, payment and shipping method.
The order is created, but it shown in sales->orders grid with incorrect G.T. Purchased Price (the amount for USD and EUR are the same)
The orders placed thorugh magento front end have correct G.T. Purchased price the initial price in USD (92 USD) and converted price for store in EUR(66 EUR). But orders which is created using code shows the same amount converted in EUR(66 EUR) and USD (66 USD). I would very appreciate if you help me to make the price shown correctly in the order.
Thank you for your help
To convert a price from currency of store view in which the order is placed to the base currency (which Magento is setup with and is shown in the admin), use the following code:
$basePrice = Mage::app()->getStore()->convertPrice($price, false, false);

Resources