Magento - 单笔优惠券标记为待付款时使用

时间:2012-11-07 11:34:25

标签: php sql magento paypal coupon

我遇到了Magento单一优惠券代码的问题,该代码被标记为在客户点击下订单按钮时使用。如果Paypal付款失败或客户在订单完成之前离开页面,他将无法返回并重新订购此优惠券,该优惠券设置为仅使用一次,并且已被标记已使用过。< / p>

我找到了一段代码,减少了优惠券被用户使用的次数,并允许他重复使用优惠券。不幸的是,他在单击下订单按钮时​​尝试连接Paypal页面时出错。为了能够再次使用优惠券并访问Paypal页面,我必须使用此客户的ID删除表 salesrule_coupon_usage salesrule_customer 中SQL数据库中的行。

以下是我需要更改以自动删除客户ID的优惠券使用信息的代码:

public function cancel($observer)
{
    $order = $observer->getEvent()->getPayment()->getOrder();
    if ($order->canCancel()) {
        if ($code = $order->getCouponCode()) {
            $coupon = Mage::getModel('salesrule/coupon')->load($code, 'code');
            if ($coupon->getTimesUsed() > 0) {
                $coupon->setTimesUsed($coupon->getTimesUsed() - 1);
                $coupon->save();
            }

            $rule = Mage::getModel('salesrule/rule')->load($coupon->getRuleId());
            error_log("\nrule times used=" . $rule->getTimesUsed(), 3, "var/log/debug.log");
            if ($rule->getTimesUsed() > 0) {
                $rule->setTimesUsed($rule->getTimesUsed()-1);
                $rule->save();
            }

            if ($customerId = $order->getCustomerId()) {
                if ($customerCoupon = Mage::getModel('salesrule/rule_customer')->loadByCustomerRule($customerId, $rule->getId())) {
                    $couponUsage = new Varien_Object();
                    Mage::getResourceModel('salesrule/coupon_usage')->loadByCustomerCoupon($couponUsage, $customerId, $coupon->getId());

                    if ($couponUsage->getTimesUsed() > 0) {
                        /* I can't find any #@$!@$ interface to do anything but increment a coupon_usage record */
                        $resource = Mage::getSingleton('core/resource');
                        $writeConnection = $resource->getConnection('core_write');
                        $tableName = $resource->getTableName('salesrule_coupon_usage');

                        $query = "UPDATE {$tableName} SET times_used = times_used-1 "
                            .  "WHERE coupon_id = {$coupon->getId()} AND customer_id = {$customerId} AND times_used > 0";

                        $writeConnection->query($query);
                    }

                    if ($customerCoupon->getTimesUsed() > 0) {
                        $customerCoupon->setTimesUsed($customerCoupon->getTimesUsed()-1);
                        $customerCoupon->save();
                    }
                }
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我相信这是一个从1.4到1.6左右的旧bug。但是,无论你是否有旧版本,如果你知道你在Magento周围的方式,这可以很容易地修复。

问题是,您有代码在点击付款按钮时更新salesrule_coupon_usage表。这根本不是你想要的。您希望将其包含在付款交易中。我不知道这个错误是否发生,因为你有自定义代码或者使用旧版本的Magento,但我会告诉你将如何解决这个问题。然后我会给你一个类似你提议的修复:

Magento已经有了一个叫做“交易”的抽象概念。事务用于放置和组合对象,这些对象需要全部成功或全部失败,没有半量级。 Magento将完成交易并尝试保存您放入其中的每个对象。如果其中任何一个失败(例如,付款未通过),则已经保存的所有事件都将“回滚”。

幸运的是,Magento已经创建了一个交易对象来处理在成功付款时需要一起更新的各种事情的付款。您可以使用该交易并使用它来正确更新优惠券使用情况。

以下是您需要做的10000英尺视图。

  • 过早查找正在更新salesrule_coupon_usage表的内容并将其删除。我们将添加我们自己的事务安全版本,因此我们不希望它被保存在其他任何地方。最简单的方法是找出连接到该表的模型,并搜索该模型的创建。对于1.7和1.8,这是规则/客户模型。
  • 创建观察员以捕获付款交易的开始。在magento的大多数现代版本中,此事件称为sales_order_payment_place_start,可在app / code / core / Mage / Sales / Model / Order / Payment.php
  • 中见证。
  • 从活动中拉出订单并将优惠券代码拉出活动。
  • 拉出要更新的实际型号。看起来有人在你的代码中找不到它,但应该有一些模型使用salesrule_coupon_usage表隐藏在某个地方。搜索.xml文件中的“salesrule_coupon_usage”并查看使用该表的模型。同样,对我而言,1.7,这是规则/客户模型。
  • 加载该型号,客户更改优惠券代码所涉及的值,以表明客户已使用优惠券,但尚未保存。
  • 将事务从事件中取出,并使用addObject方法注册更新的优惠券对象。

你做完了。事务将自动尝试保存已添加到其中的所有对象。如果任何部分失败(包括付款失败),它将回滚整个过程并且您的优惠券将不会被使用。好极了!

现在,在我看来,以上是解决问题的最佳方法,但如果您因某些原因遇到问题,可以选择基于捕获不成功的付款然后使用您的代码。

再次,这是10,000英尺的视图:

  • 创建观察员以捕获失败的付款事件。在大多数版本中,您需要的事件是sales_order_payment_cancel。
  • 运行你已经拥有的代码......它应该这样做。但要澄清其他人:
    • 将订单拉出活动,拉出优惠券代码和客户ID。
    • 更新customer,rule和salesrule_coupon_usage表。 (虽然确实应该有一个模型,但我相信你能找到它)

现在,当销售失败时,您将返回并手动展开所有内容。这不像我的第一个解决方案那么干净,但根据您对Magento的熟悉程度,对您来说可能更容易。

我很确定Magento新的,干净的版本没有这个问题,所以让我提供一个相当明显的建议作为第三个解决方案。

  • 更新Magento
  • 如果Magento是最新的,请测试禁用任何自定义模块,因为有些东西破坏了它。我注意到Amasty优惠券插件特别错误。
  • 如果你对Magento核心进行了自定义更改......祝你好运。
祝你好运!