I'm integrating a system with Magento.
When I create an order, if my non-Magento system indicates the order does have a coupon I would like to mark the coupon code as "used" for that customer, so the next time he tries to use it, Magento will know that customer already used it.
How can I accomplish this?
I manage to do it like this:
$coupon = mage::getModel('salesrule/coupon')->load($code, 'code');
$coupon->setTimesUsed($coupon->getTimesUsed()+1);
$coupon->save();
$rule = Mage::getModel('salesrule/rule')->load($coupon->getRuleId());
$rule->setTimesUsed($rule->getTimesUsed()+1);
$rule->save();
$couponUsage = Mage::getResourceModel('salesrule/coupon_usage');
$couponUsage->updateCustomerCouponTimesUsed($customerId,$coupon->getCouponId());
Thanks to this post:
Magento - Single Coupon marked as used when payment pending
Set the Shopping Cart Rule's Uses per Customer to 1.
----EDIT----
If you want to apply the coupon in your code then you can do something like this:
$coupon_code = "YOUR_CODE";
Mage::getSingleton('checkout/cart')
->getQuote()
->setCouponCode($coupon_code)
->collectTotals()
->save();
Related
I want to display the discounted price the client can have depending on the payment method he chooses directly on the product page.
Basically, what I need is a way to get the shopping cart rules that apply for payment methods. So then I could use it to build a table of payment methods X discounts like this:
Cash: $90 (10% discount)
CC: $100 (Full price)
Transfer: $100 (Full price)
So far I couldn't find a way to access the shopping cart rules. Any insights?
UPDATE:
For those wondering, I've found a way to get the shopping cart rules. Pretty simple actually:
$model = Mage::getModel('salesrule/rule')
->getCollection();
With this information I can loop through the rules and find the ones that apply to payment methods.
$conditions = unserialize($item['conditions_serialized']);
But I realized that this way is too much work and can get complex if rules are complex. I decided to get the rules that I want by ID and get the discount value, since it won't change all the time.
If you know how to make Magento calculate everything for me, like me asking "If a user chose this payment method, besides everything else (user group, catalog discounts, etc) what would be the final price?".
$model = Mage::getModel('salesrule/rule')
->getCollection();
foreach($model as $item){
// check, do whatever and get discount
}
I'm developing a script (external to Magento, not a module) which aims to output a text list of all available products, their prices and some other attributes. However, catalog price rules don't seem to be applied to product prices. If I use any of the following:
$_product->getPrice()
$_product->getFinalPrice()
I get the normal price (without rules being applied).
If I use:
$_product->getSpecialPrice()
I get null unless the product actually has a special price inserted in the product itself (i.e. if special price is not related with catalog rules).
I also tried
Mage::getModel('catalogrule/rule')->calcProductPriceRule($product,$product->getPrice())
as suggested in the answer given by Fabian Blechschmidt, but interestingly it returns the normal price only if the product is affected by any catalog rule, returning null otherwise.
There was a similar question in StackOverflow and Magento Forums some time ago, but the provided answer (which is to insert the code bellow) doesn't work for me (returned prices remain the same).
Mage::app()->loadAreaPart(Mage_Core_Model_App_Area::AREA_FRONTEND,Mage_Core_Model_App_Area::PART_EVENTS);
Does anybody have an idea of how to achieve this?
I'm using Magento 1.6.2.0.
Thanks in advance.
Thanks to you, I found a new site:
http://www.catgento.com/magento-useful-functions-cheatsheet/
And they mentioned:
Mage::getModel('catalogrule/rule')->calcProductPriceRule($product,$product->getPrice())
HTH
As catalog price rules heavily depend on time, store and visiting customer, you need to set those parameters when you want to retrieve the product final price with it's price rules applied.
So, in your case, make sure that provided product is passed with the desired store and customer group id, which can be set as:
Mage::getModel('catalogrule/rule')->calcProductPriceRule($product->setStoreId('STORE_ID')->setCustomerGroupId('CUSTOMER_GROUP_ID'),$product->getPrice())
I discovered the problem. The discounted prices display Ok in the store frontend. The problem was that I was developing a script "external" to Magento (thus not a Magento module), something like:
<?php
set_time_limit(0);
ignore_user_abort();
error_reporting(E_ALL^E_NOTICE);
header("Content-Type: text/plain; charset=utf-8");
require_once "app/Mage.php";
// Get default store code
$default_store = Mage::app()->getStore();
...
For everything to work properly it seems that one must follow the proper Magento bootstrap, and develop everything as a module. My script was so simple that I thought it wouldn't be necessary to code a complete module. In other words, everything in Magento should really be a module.
Concluding, using the module approach, all the methods work as expected:
$_product->getPrice()
$_product->getFinalPrice()
$_product->getSpecialPrice()
Thank you all for your input.
This helped me in this issue: http://www.magentocommerce.com/boards/viewthread/176883/
. Jernej's solution seems plausible, but it does not handle rules that Overwrite other rules by using 'stop processing' and therefore can apply more than one rule.
$original_price = $_product->getPrice();
$store_id = 1; // Use the default store
$discounted_price = Mage::getResourceModel('catalogrule/rule')->getRulePrice(
Mage::app()->getLocale()->storeTimeStamp($store_id),
Mage::app()->getStore($store_id)->getWebsiteId(),
Mage::getSingleton('customer/session')->getCustomerGroupId(),
$_product->getId());
// if the product isn't discounted then default back to the original price
if ($discounted_price===false) {
$discounted_price=$original_price;
}
We have added a "yes/no" product attribute labelled: "Allow this product to have coupons applied?" with a default value of "yes".
The reason for this is, that we never want the sales team to give discounts on certain core products out of the thousands available.
We could add these products as SKU's to every one of the thousand coupons created, but that can then be changed by accident, or improperly listed by the sales team creating the coupons.
We therefore have asked them to add this rule to their new coupons, to exclude these products. We also updated all the other coupons via code, to include this rule.
When I test the rule on Magento 1.5, Community edition, it does exactly the opposite of what the condition says.
When I test the same rule on our other Enterprise solution (magento 1.9), it actually does what it is supposed to.
When I have one product in the shopping cart, being a product that has this attribute set to "No", and I apply a coupon code, it accepts the coupon code. On the other system (Enterprise) it rejects it, as it should.
Has anyone else came across this?
UPDATE:
Ok, this just got more interesting.
When I stepped through the Rule classes, the product was passed, but the product attribute did not come through. The scope is set to website, and I did check that is it saved under that scope in the back end.
This is really weird...
On the enterprise system, the product attribute, with the same configuration and data is coming through.
I even tried to not have double negatives, with another new attribute, to make sure.
Running against the following rule, the coupon gets refused: "Coupon code is not valid."
This is correct, as the product is set as "Can use coupon? = No".
But the problem is that I do not want to do a check against all the other products, but rather against, the few that has been marked as "No".
This is not going to work for us anyway, as we don't want to apply a coupon if there is any product in the cart that has a value of "No" for the attribute "Can use coupon?".
This is a double negative rule, no matter which way you look at it.
I stepped through /app/code/core/Mage/SalesRule/Model/Rule/Condition/Product.php through the validate() function, when adding the product a second time, and the data shows up in the attributes, but when I go and re-apply the coupon, and step through this function again, those values are gone. this is weird.
When adding new product to shopping cart:
When Re-applying Coupon Code:
Where the heck did description and some of the other attributes disappear to?
UPDATE NOTE I am getting a bit closer.
When I change the following validate() function in "/app/code/core/Mage/SalesRule/Model/Rule/Condition/Product.php" from the following:
public function validate(Varien_Object $object)
{
$product = false;
if ($object->getProduct() instanceof Mage_Catalog_Model_Product) {
$product = $object->getProduct();
} else {
$product = Mage::getModel('catalog/product')
->load($object->getProductId());
}
$product
->setQuoteItemQty($object->getQty())
->setQuoteItemPrice($object->getPrice())
->setQuoteItemRowTotal($object->getBaseRowTotal());
return parent::validate($product);
}
To This:
public function validate(Varien_Object $object)
{
$product = false;
$product = Mage::getModel('catalog/product')
->load($object->getProductId());
$product
->setQuoteItemQty($object->getQty())
->setQuoteItemPrice($object->getPrice())
->setQuoteItemRowTotal($object->getBaseRowTotal());
return parent::validate($product);
}
It then works fine!
Found out the actual problem, and here is what I did for the solution:
The following bit gets the product data for the Shopping Cart Price Rules:
if ($object->getProduct() instanceof Mage_Catalog_Model_Product) {
$product = $object->getProduct();
} else {
$product = Mage::getModel('catalog/product')
->load($object->getProductId());
}
The culprit is this line: $product = $object->getProduct();
That calls a line from the "Quote/Item/Abstract.php" being: $product = $this->_getData('product');
It will simply get the cached data from the system, and that consists of a selection like this:
$productCollection = Mage::getModel('catalog/product')->getCollection()
->setStoreId($this->getStoreId())
->addIdFilter($this->_productIds)
->addAttributeToSelect(Mage::getSingleton('sales/quote_config')->getProductAttributes())
->addOptionsToResult()
->addStoreFilter()
->addUrlRewrite()
->addTierPriceData();
The problem with this is, the following line:
->addAttributeToSelect(Mage::getSingleton('sales/quote_config')->getProductAttributes())
That will get only the attributes defined in the Config.xml for quote items being:
<quote>
<item>
<product_attributes>
<sku/>
<type_id/>
<name/>
<status/>
<visibility/>
<price/>
<weight/>
<url_path/>
<url_key/>
<thumbnail/>
<small_image/>
<tax_class_id/>
<special_from_date/>
<special_to_date/>
<special_price/>
<cost/>
<is_recurring/><!-- for totals calculation, placing and processing order -->
<recurring_profile/><!-- for placing order -->
<gift_message_available/>
</product_attributes>
</item>
</quote>
This will not get the new custom attribute that I want, and the rule will never be able to compare the data with the expected value properly.
Adding the following xml to my custom sales module config.xml, which have some observers in it for other stuff, fixes the problem.
<sales>
<quote>
<item>
<product_attributes>
<exclude_from_coupon/>
</product_attributes>
</item>
</quote>
</sales>
Then it all works!
Why did it work in the enterprise version of magento
Don't really know. I think Enterprise is maybe looking for settings on the actual Attribute definition, and includes it to the list of Attributes to collect, and then return the data for it, my guess. I will research that, and update it here to the post.
At least I now know what the real issue is, and why the Shopping Cart Rule Condition (coupon) failed.
Thanks to all those who helped me with some good questions and suggestions.
Another day wiser with magento...
I tested this with Magento CE 1.5.1.0 and cannot reproduce your problem. For me, it works.
Please recheck the following for your CE installation:
You set the default attribute value to "yes"
You did reindex the indexes as required.
You edited one test product and explicitly set the attribute value to "no".
(Just to be sure) You updated the caches.
You set the shopping cart price rule exactly as described above (apply if conditions are FALSE and allow is set to NO).
If you don't have any custom code interfering, this should work. It does in the default installation.
If it still doesn't work:
What happens if you rephrase the condition to only apply if all conditions are TRUE and allow is set to TRUE (does remove the double negative which is more complicated)?
Please post screenshots of the backend forms for shopping cart price rule, product attribute and the product.
I need to know, if any solution how to add in magento success.phtml order's total price?
Because I want after placed order, customer get all info how to make payment including what price need to pay, because customer don't remember in last step what is total price.
You could use something like this in your success.phtml:
$sOrderId = Mage::getSingleton('checkout/session')->getLastOrderId();
$oOrder = Mage::getModel('sales/order')->load($sOrderId);
echo $oOrder->getGrandTotal();
in success.phtml template you can use
$order = Mage::getModel('sales/order')->loadByIncrementId($this->getOrderId());
$total = $order->getGrandTotal();
proper way is to extend the Mage_Checkout_Block_Onepage_Success and add your own method for loading the order again (As in this page quote is inactive already) as it is not nice to load such stuff in templates
I'm struggling to figure out how to display the percentage or the amount of discount that is applied to a product in Magento via the Catalog Price Rules.
For example: I want the price to be displayed in the front-end as follows: [old-price] [special-price] [discount info] where [old-price] has a css strike through.
The [old-price] and [special-price] is available by default through the tax helper. I've tried using the CatalogRule model, but I have no way to load it with a product id as the load function expects an entity id and from what I can tell, there aren't any other useful methods to load by product ID. I've var dumped (as well as using get_class_methods) just about everything that I found in the price.phtml file (apart from $this of course), but nothing helps.
I could just use a simple calculation to work out the discount percentage or amount, but I have no way of knowing whether the catalog rule is based on a percentage, or fixed amount.
I hope this all makes sense?Thanks for the help.Rémy
I do agree Magento makes this kind of thing a bit too hard. I wanted to display the description of the coupon code next to the entered coupon code. I suspect my code will be able to help you on your way. I put this code at the top in the template checkout/cart/coupon.phtml:
<?php
$c = Mage::getResourceModel('salesrule/rule_collection');
$c->addBindParam('coupon_code', $this->getCouponCode());
$c->getSelect()->where("coupon_code is null or coupon_code='' or coupon_code=:coupon_code");
foreach ($c->getItems() as $item) {
$coupon_description = $item->getDescription();
}
?>
So you can see $coupon_description now holds the description of the Shopping Cart Price Rule as long as the user specified a coupon code. You can add more properties from the coupon this way.