If we applied coupon code and completed order.
Once we cancel the order, then coupon code should become applicable again, but it can't be used anymore. Please help me, it's strange default Magento behavior.
Please help me soon.
Magento Stack Exchange is a question and answer site for users of the Magento e-Commerce platform. It only takes a minute to sign up.
Sign up to join this communityThis is default Magento behaviour - if the payment fails / the order is canceled before it, then the coupon code will not be free to be reused.
There're few modules that change this behaviour. Quick googling gave me f/e:
http://magetechno.com/cancel-order-coupon-code-reuse.html
Here's description for the situation: http://magebase.com/magento-tutorials/quick-fix-coupon-codes-used-up-on-incomplete-transactions/
To avoid link being removed and for future reference I'm copy-pastying the contents of that post: (all credits go to MageBase.com for this solution, it's untested but from the looks of it - should do it's job):
app/code/local/Orchid/CouponFix/Model/Observer.php
<?php
class Orchid_CouponFix_Model_Observer
{
public function cancel($observer)
{
$event = $observer->getEvent();
$order = $event->getPayment()->getOrder();
if ($order->canCancel()) {
if ($code = $order->getCouponCode()) {
$coupon = Mage::getModel('salesrule/rule')->load($code, 'coupon_code');
$coupon->setTimesUsed($coupon->getTimesUsed()-1);
$coupon->save();
if($customerId = $order->getCustomerId()) {
if ($customerCoupon = Mage::getModel('salesrule/rule_customer')->loadByCustomerRule($customerId, $coupon->getId())) {
$customerCoupon->setTimesUsed($customerCoupon->getTimesUsed()-1);
$customerCoupon->save();
}
}
}
}
}
app/code/local/Orchid/CouponFix/etc/config.xml
<config>
<modules>
<Orchid_CouponFix>
<version>0.1.0</version>
</Orchid_CouponFix>
</modules>
<global>
<models>
<couponfix>
<class>Orchid_CouponFix_Model</class>
</couponfix>
</models>
<events>
<sales_order_payment_cancel>
<observers>
<orchid_couponfix_observer>
<type>singleton</type>
<class>Orchid_CouponFix_Model_Observer</class>
<method>cancel</method>
</orchid_couponfix_observer>
</observers>
</sales_order_payment_cancel>
</events>
</global>
</config>
app/etc/modules/Orchid_CouponFix.xml
<?xml version="1.0"?>
<config>
<modules>
<Orchid_CouponFix>
<active>true</active>
<codePool>local</codePool>
</Orchid_CouponFix>
</modules>
</config>
Orchid
module, when i try to cance lthe order i got theis error : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'salesrule.coupon_code' in 'where clause', query was: SELECT
salesrule.* FROM
salesrule` WHERE (salesrule
.coupon_code
='123456')` please help me
Jul 15, 2016 at 9:24
You could create an event observer for order_cancel_after
. Then if the order was placed by a customer ($order->getCustomerId() > 0
), you can update the salesrule_coupon_usage
table and lower the value of times_used
for this coupon.
coupon_code
attribute of an order and keep in mind that some extensions may accept more than one code and separate them by commas: $couponCodes = explode(',', $order->getCouponCode());
coupon_id
, see Mage_SalesRule_Model_Coupon::loadByCode()
times_used
, you could check Mage_SalesRule_Model_Resource_Coupon_Usage::updateCustomerCouponTimesUsed()
, which increases times_used
The accepted answer doesn't work for me in Magento 1.9.3+ So i modified and added some code to the observer cancel function. This should do the trick:
public function cancel($observer)
{
$event = $observer->getEvent();
$order = $event->getPayment()->getOrder();
if ($order->canCancel()) {
$customerId = $order->getCustomerId();
$code = $order->getCouponCode();
if ($code) {
$rule = Mage::getModel('salesrule/rule')->load($code, 'name');
$rule->setTimesUsed($rule->getTimesUsed() - 1);
$rule->save();
$coupon = Mage::getModel('salesrule/coupon')->loadByCode($code);
$coupon->setTimesUsed($coupon->getTimesUsed() - 1);
$coupon->save();
if ($customerId) {
/* @var Mage_SalesRule_Model_Resource_Coupon_Usage $couponUsage */
$couponUsage = Mage::getResourceModel('salesrule/coupon_usage');
$couponUsage->getReadConnection()->delete($couponUsage->getMainTable(), [
'coupon_id = ?' => $coupon->getId(),
'customer_id = ?' => $customerId
]);
$customerCoupon = Mage::getModel('salesrule/rule_customer')->loadByCustomerRule($customerId, $rule->getId());
if ($customerCoupon) {
$customerCoupon->setTimesUsed($customerCoupon->getTimesUsed() - 1);
$customerCoupon->save();
}
}
}
}
}
I tried the above answer by @Jesse Visser in my Magento 1.9.0.1 but when I try to place an order it gives an error to try again later so I have updated the above code, any improvement on my below code would be great.
<?php
class Orchid_CouponFix_Model_Observer
{
public function cancel($observer)
{
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$readConnection = $resource->getConnection('core_read');
$event = $observer->getEvent();
$order = $event->getPayment()->getOrder();
if ($order->canCancel()) {
if ($code = $order->getCouponCode()) {
$coupon = Mage::getModel('salesrule/coupon')->load($code, 'code');
$coupon_id = $coupon->getCouponId();
$rule_id = $coupon->getRuleId();
if($customerId = $order->getCustomerId()){
// Update or Delete record in salesrule_coupon_usage Table
$tableName = $resource->getTableName('salesrule_coupon_usage');
$query = "SELECT * FROM {$tableName} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$query = "DELETE FROM {$tableName} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
}
$writeConnection->query($query);
// Update or Delete record in salesrule_customer Table
$tableName = $resource->getTableName('salesrule_customer');
$query = "SELECT * FROM {$tableName} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$query = "DELETE FROM {$tableName} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
}
$writeConnection->query($query);
}
}
}
}
}
Cheers
For CE 1.7.0.2 installations with all security patches installed (up to SUPEE10975), the salesrule_coupon table must also be updated, Obeserver.php updated:
<?php
class Orchid_CouponFix_Model_Observer
{
public function cancel($observer)
{
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$readConnection = $resource->getConnection('core_read');
$event = $observer->getEvent();
$order = $event->getPayment()->getOrder();
if ($order->canCancel()) {
if ($code = $order->getCouponCode()) {
$coupon = Mage::getModel('salesrule/coupon')->load($code, 'code');
$coupon_id = $coupon->getCouponId();
$rule_id = $coupon->getRuleId();
if($customerId = $order->getCustomerId()){
// Update or Delete record in salesrule_coupon_usage Table
$tableName = $resource->getTableName('salesrule_coupon_usage');
$query = "SELECT * FROM {$tableName} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$query = "DELETE FROM {$tableName} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
}
$writeConnection->query($query);
// Update record in salesrule_coupon Table
$tableName = $resource->getTableName('salesrule_coupon');
$query = "SELECT * FROM {$tableName} WHERE coupon_id={$coupon_id}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$coupon_usage = 0;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE coupon_id={$coupon_id}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE coupon_id={$coupon_id}";
}
$writeConnection->query($query);
// Update or Delete record in salesrule_customer Table
$tableName = $resource->getTableName('salesrule_customer');
$query = "SELECT * FROM {$tableName} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$query = "DELETE FROM {$tableName} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
}
$writeConnection->query($query);
}
}
}
}
}
1.9
if ($code = $order->getCouponCode()) {
$resource = Mage::getSingleton('core/resource');
$writeConnection = $resource->getConnection('core_write');
$readConnection = $resource->getConnection('core_read');
$coupon = Mage::getModel('salesrule/coupon')->load($code, 'code');
$coupon_id = $coupon->getCouponId();
$rule_id = $coupon->getRuleId();
// Update record in salesrule_coupon Table
$tableName = 'salesrule_coupon';
$query = "SELECT * FROM {$tableName} WHERE coupon_id={$coupon_id}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage > 0){
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE coupon_id={$coupon_id}";
}
$writeConnection->query($query);
if($customerId = $order->getCustomerId()){
// Update or Delete record in salesrule_coupon_usage Table
$tableName = 'salesrule_coupon_usage';
$query = "SELECT * FROM {$tableName} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$query = "DELETE FROM {$tableName} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE coupon_id={$coupon_id} AND customer_id={$customerId}";
}
$writeConnection->query($query);
// Update or Delete record in salesrule_customer Table
$tableName = 'salesrule_customer';
$query = "SELECT * FROM {$tableName} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
$coupon_usage = $readConnection->fetchAll($query);
$coupon_usage = $coupon_usage[0]['times_used'];
if($coupon_usage==1){
$query = "DELETE FROM {$tableName} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
}else{
$coupon_usage = $coupon_usage-1;
$query = "UPDATE {$tableName} SET times_used={$coupon_usage} WHERE rule_id={$rule_id} AND customer_id={$customerId}";
}
$writeConnection->query($query);
}
}