Add custom discount order in total with button

2020-06-28 01:13发布

I have my module with my custom discount and it's OK.

config.xml:

<sales>
   <quote>
       <totals>
             <aver> 
                <class>Dani_Prueba_Model_Total_Aver</class> 
                <after>subtotal</after> 
             </aver>
        </totals>
    </quote>
</sales>

My module:

<?php
class Dani_Prueba_Model_Total_Aver extends Mage_Sales_Model_Quote_Address_Total_Abstract{

    public function collect(Mage_Sales_Model_Quote_Address $address){

        $baseDiscount = 2.5;
        $discount = Mage::app()->getStore()->convertPrice($baseDiscount);

        $address->setCustomDiscount($baseDiscount);

        $address->setBaseGrandTotal($address->getBaseGrandTotal() - $baseDiscount);
        $address->setGrandTotal($address->getGrandTotal() - $discount);

        return $this;
    }

    public function fetch(Mage_Sales_Model_Quote_Address $address){
        $this->setCode('aver');
        $amount = $address->getCustomDiscount();
            if ($amount != 0){
                $address->addTotal(array(
                'code'  => $this->getCode(),
                'title' => 'Custom Discount',
                'value' => $amount
            ));
        }
        return $this;
    }
}

This it is OK and when I add a product to cart, automatically apply my custom discount.

But now I need do it with a button. When I add products to cart not apply discount and have the correct total. But when I click a button, apply my custom discount, and with other button "Cancel", cancel the discount. I need some similar like the function a coupon code.

How I do it??

3条回答
一纸荒年 Trace。
2楼-- · 2020-06-28 01:36

To do this, you will need to add another attribute/column to the sales/quote table (and possibly sales/order table).

So, in your install script, execute this (I included the sales/order table/entity attribute as well):

$installer->addAttribute('order', 'use_special_coupon', array('type' => 'int', 'grid' => true, 'source' => 'adminhtml/system_config_source_yesno'));
$installer->addAttribute('quote', 'use_special_coupon', array('type' => 'int', 'grid' => true, 'source' => 'adminhtml/system_config_source_yesno'));
$installer->getConnection()->addColumn($installer->getTable('sales/quote'), 'use_special_coupon', 'TINYINT(1) unsigned default 0');
$installer->getConnection()->addColumn($installer->getTable('sales/order'), 'use_special_coupon', 'TINYINT(1) unsigned default 0');

Then, in your controller, do something like this:

$quote = Mage::getSingleton('checkout/session')->getQuote();
$quote
    ->setUseSpecialCoupon(true)
    ->save();

Or, the opposite, in your removeAction:

$quote = Mage::getSingleton('checkout/session')->getQuote();
$quote
    ->setUseSpecialCoupon(false)
    ->save();

And, then finally, in your total model, modify it to be this:

<?php
class Dani_Prueba_Model_Total_Aver extends Mage_Sales_Model_Quote_Address_Total_Abstract{

    public function collect(Mage_Sales_Model_Quote_Address $address)
    {
        if ($address->getQuote()->getUseSpecialCoupon()) {
            $baseDiscount = 2.5;
            $discount = Mage::app()->getStore()->convertPrice($baseDiscount);

            $address->setCustomDiscount($baseDiscount);

            $address->setBaseGrandTotal($address->getBaseGrandTotal() - $baseDiscount);
            $address->setGrandTotal($address->getGrandTotal() - $discount);
        }
        return $this;
    }

    public function fetch(Mage_Sales_Model_Quote_Address $address){
        if ($address->getQuote()->useSpecialCoupon()) {            
            $this->setCode('aver');
            $amount = $address->getCustomDiscount();
            if ($amount != 0){
                $address->addTotal(array(
                    'code'  => $this->getCode(),
                    'title' => 'Custom Discount',
                    'value' => $amount
                ));
            }
        }
        return $this;
    }
}
查看更多
我想做一个坏孩纸
3楼-- · 2020-06-28 01:43

Joseph Maxwell, thank you for the great solution! However,

if ($address->getQuote()->useSpecialCoupon())

This code should be changed to the following one

if ($address->getQuote()->getUseSpecialCoupon())

Without GET word I have faced the following error:

Invalid method Mage_Sales_Model_Quote::useSpecialCoupon(Array

and spent some time until I realized the reason of the error.

查看更多
乱世女痞
4楼-- · 2020-06-28 01:50

As a followup to the accepted answer, I'd like to point out that people (like me from the past) who are having trouble getting their custom totals reflected on invoices will need to add a few more things.

First, your column needs to be added to the sales/invoice table, as well.

Second, Mage_Sales uses Convert objects to propagate data from quotes to orders to invoices. To get your_custom_total included in this flow, add a couple config hooks:

<global>
    <fieldsets>
        <sales_convert_quote>
            <your_custom_total><to_order>*</to_order></your_custom_total>
        </sales_convert_quote>
        <sales_convert_order>
            <your_custom_total><to_invoice>*</to_invoice></your_custom_total>
        </sales_convert_order>
    </fieldsets>
</global>

Now your total will be included when a quote is converted to an order, and that order to an invoice.

However, even though your total is saved on the invoice, the invoice does not know how that total affects its grand total. Thus, an invoice total model similar to the quote address total model needs to be added.

The config hook:

<global>
    <sales>
        <order_invoice>
            <totals>
                <namespace_custom>
                    <class>namespace/sales_order_invoice_total_custom</class>
                    <after>subtotal</after>
                </namespace_custom>
            </totals>
        </order_invoice>
    </sales>
</global>

And the class:

class Package_Module_Model_Sales_Order_Invoice_Total_Custom extends Mage_Sales_Model_Order_Invoice_Total_Abstract
{
    public function collect(Mage_Sales_Model_Order_Invoice $invoice)
    {
        $invoice->setBaseGrandTotal($invoice->getBaseGrandTotal() + $invoice->getYourCustomTotal())
            ->setGrandTotal($invoice->getGrandTotal() + $invoice->getYourCustomTotal());
        return $this;
    }
}

You can mirror the above for converting invoices to credit memos as well, if your total is applicable.

This link http://magento.ikantam.com/qa/how-add-discount-total-magento explains how to rewrite adminhtml blocks to show your total on the backend.

查看更多
登录 后发表回答