0

In order to calculate a discount based on quantity of items in the cart that will take in consideration also the different weight of modifiers (suppose I sell the same product in different containers weighing from 1 to 210kg), I came up with an extension which grabs the $item->$item_qty at every order update, multiplies that value with the $item->sku, adds to the total of Kg being orderd and, based on a table of different discounts hardcoded with conditionals in the extension's php file, calculates the discount to be applied.

I can't seem to pass the $order->$order_discount to the actual order. When I submit the form, the order total doesn't take into account the calculated discount.

Here's my code

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Store Discount Extension
 *
 * @package     ExpressionEngine
 * @subpackage  Addons
 * @category    Extension
 * @author      Milksamsa
 * @link        http://
 */

class Store_discount_ext {

public $settings        = array();
public $description     = 'Force discount based on item quantity and SKU multiplier';
public $docs_url        = 'http://';
public $name            = 'SKUdiscount';
public $settings_exist  = 'n';
public $version         = '1.0';

private $EE;

/**
 * Constructor
 *
 * @param   mixed   Settings array or empty string if none exist.
 */
public function __construct($settings = '')
{
    $this->EE =& get_instance();
    $this->settings = $settings;
}

// ----------------------------------------------------------------------

/**
 * Activate Extension
 *
 * This function enters the extension into the exp_extensions table
 *
 * @see http://codeigniter.com/user_guide/database/index.html for
 * more information on the db class.
 *
 * @return void
 */
public function activate_extension()
{
    // Setup custom settings in this array.
    $this->settings = array();

    // Add hooks
    $data = array(
        'class'     => __CLASS__,
        'method'    => 'update_cart',
        'hook'      => 'store_order_recalculate_end',
        'settings'  => serialize($this->settings),
        'priority'  => 10,
        'version'   => $this->version,
        'enabled'   => 'y'
    );

    $this->EE->db->insert('extensions', $data);
}

// ----------------------------------------------------------------------

/**
 * Disable Extension
 *
 * This method removes information from the exp_extensions table
 *
 * @return void
 */
function disable_extension()
{
    $this->EE->db->where('class', __CLASS__);
    $this->EE->db->delete('extensions');
}

// ----------------------------------------------------------------------

/**
 * Update Extension
 *
 * This function performs any necessary db updates when the extension
 * page is visited
 *
 * @return  mixed   void on update / false if none
 */
function update_extension($current = '')
{
    if ($current == '' OR $current == $this->version)
    {
        return FALSE;
    }

    $this->EE->db->where('class', __CLASS__);
    $this->EE->db->update(
                'extensions',
                array('version' => $this->version)
    );
}

// ----------------------------------------------------------------------

/**
 * Responds to the store_cart_update_end hook in Exp:resso Store
 * to apply a discount to each product, as needed
 *
 * @return array of cart items
 */
function update_cart($order)
{

    if ($this->EE->extensions->last_call)
    {
        $order = $this->EE->extensions->last_call;
    }

    // Get the number of products currently in the user's cart
     $order->order_discount = 0;
     $total_q = 0;

      foreach ($order->items as $item) {
                $sku = $item->sku;
                $item_q = $item->item_qty * $sku;
                $total_q = $total_q + $item_q; 
            }

     if ($total_q >= 24 && $total_q < 30){
     $order->order_discount = $total_q  * 0.5;
     }

     if ($total_q >= 30 && $total_q < 60){
     $order->order_discount = $total_q  * 0.6;
     }

     if ($total_q >= 60 && $total_q < 100){
     $order->order_discount = $total_q * 0.95;
     }

     if ($total_q >= 100 && $total_q < 200){
     $order->order_discount = $total_q * 1.5;
     }

     if ($total_q >= 200 && $total_q < 210){
     $order->order_discount = $total_q * 1.55;
     }

     if ($total_q >= 210){
     $order->order_discount = $total_q * 1.7;
     }

     return $order_discount;
}
}

/* End of file ext.store_discount.php */
/* Location: /third_party/store_discount/ext.store_discount_batch.php */

//UPDATE

I've followed this procedure: https://gist.github.com/bryantAXS/10882383 Not sure where to go from here. I've not included the calculations for now, for testing purpose I've limited the discount amount to 4.

  • I created a new folder in third_party named store_helpers
  • I created a new folder in there named store_helpers/classes
  • I created a CustomDiscountAdjuster.php class inside it
  • I created a ext.store_helpers.php file in third_party/store_helpers

My CustomDiscountAdjuster.php file contains:

<?php

// Inside our custom third_party addon folder, /third_party/store_helpers, we have a folder called "classes."
// Within the classes directory we have this file, which holds our custom build Adjuster Class.
//
// You should be able to see how this class is passed our $order object, and then instantiates a new 
// Order Adjustment object, which we use to make the adjustment. There are a few properties on the Order Adjustment
// object (nane, type, amount, etc..) that define the adjustment. The adjustment is then returned and processed.


namespace Store\Adjuster;

require PATH_THIRD.'store'.'/autoload.php';

use Store\Model\Order;
use Store\Model\OrderAdjustment;

/**
 * Calculate handling surcharge applicable to an order
 */
class CustomDiscountAdjuster implements AdjusterInterface
{
    public function adjust(Order $order)
    {


        $adjustment = new OrderAdjustment();
        $adjustment->name = "Custom Discount Adjuster";
        $adjustment->type = 'Custom Discount';
        $adjustment->amount = 10;
        $adjustment->taxable = 1;
        $adjustment->included = 1;

        return array($adjustment);



      return array();
    }

}

My ext.store_helpers.php file contains:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Store Discount Extension
 *
 * @package     ExpressionEngine
 * @subpackage  Addons
 * @category    Extension
 * @author      Milksamsa
 * @link        http://
 */

class Store_helpers_ext  {

    public $settings        = array();
    public $description     = 'Force discount based on item quantity and SKU multiplier';
    public $docs_url        = 'http://';
    public $name            = 'Store Custom EQ Discounts';
    public $settings_exist  = 'n';
    public $version         = '1.0';

    private $EE;

    /**
     * Constructor
     *
     * @param   mixed   Settings array or empty string if none exist.
     */
    public function __construct($settings = '')
    {
        $this->EE =& get_instance();
        $this->settings = $settings;
    }

    // ----------------------------------------------------------------------

    /**
     * Activate Extension
     *
     * This function enters the extension into the exp_extensions table
     *
     * @see http://codeigniter.com/user_guide/database/index.html for
     * more information on the db class.
     *
     * @return void
     */
    public function activate_extension()
    {
        // Setup custom settings in this array.
        $this->settings = array();

        // Add hooks
        $data = array(
            'class'     => __CLASS__,
            'method'    => 'update_cart',
            'hook'      => 'store_order_adjusters',
            'settings'  => serialize($this->settings),
            'priority'  => 10,
            'version'   => $this->version,
            'enabled'   => 'y'
        );

        $this->EE->db->insert('extensions', $data);
    }

    // ----------------------------------------------------------------------

    /**
     * Disable Extension
     *
     * This method removes information from the exp_extensions table
     *
     * @return void
     */
    function disable_extension()
    {
        $this->EE->db->where('class', __CLASS__);
        $this->EE->db->delete('extensions');
    }

    // ----------------------------------------------------------------------

    /**
     * Update Extension
     *
     * This function performs any necessary db updates when the extension
     * page is visited
     *
     * @return  mixed   void on update / false if none
     */
    public function store_order_adjusters($adjusters) 
    {
      $adjusters[40] = new Store\Adjuster\CustomDiscountAdjuster;
      return $adjusters;
    }

    // ----------------------------------------------------------------------

    /**
     * Responds to the store_cart_update_end hook in Exp:resso Store
     * to apply a discount to each product, as needed
     *
     * @return array of cart items
     */

}

/* End of file ext.store_discount.php */
/* Location: /third_party/store_helpers/ext.store_helpers.php */

Definitely something's going one, since taxes no longer get calculated when store_helpers extension is enabled

1 Answer 1

2

When the store_order_recalculate_end hook is fired, all calculations have already taken place. See picture.

enter image description here

So you need to calculate and set the order_total yourself.

3
  • What you mean? Should I change the hook being called? How can I force the actual order to re-calculate again? Can you actually indicate how should I change the extension?
    – Milksamsa
    Dec 27, 2014 at 7:24
  • 1
    You can't use that hook to change the item discount, it will be overwritten every time the cart is recalculated. If you create your own adjuster using the store_order_adjusters hook, then you can influence the cart recalculation. Use the DiscountAdjuster.php as an example, see: i.imgur.com/3TmI11O.png Jan 12, 2015 at 17:52
  • Please @manuel-payano, check update above.
    – Milksamsa
    Jan 20, 2015 at 15:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.