7 replies [Last post]
txcrew's picture
Offline
Joined: 09/28/2007
Juice: 103
Was this information Helpful?

Greetings community,

*** EDIT: I'm adding a $75 bounty via paypal to anyone who can figure this out for me. ***

I'm trying to setup my checkout process with the Discounts module and the Coupon module. Now before you cringe at that, I wanted to say that my questions aren't really about how to get those modules to work. More along the lines of how to get them to total properly.

Here is my scenario:

I have a Discount setup for anyone who purchases 2 or more products of 20% off. (works great)

I have a Coupon that will grant an additional 20% off. (works great)

My order totals come out like this:

Subtotal: $274.00
20% off orders of 2 products or more.: -$54.80 (20% of Subtotal)
Coupon Discount: -$54.80 (20% of Subtotal)
Subtotal excluding taxes: $164.40

As you can see there is a total here of $164.40

I'd like to get it to this:

Subtotal: $274.00
20% off orders of 2 products or more.: -$54.80 (20% of Subtotal)
Subtotal with Discount: $219.20
Coupon Discount: -$43.84 (20% of DISCOUNTED Subtotal)

Subtotal excluding taxes: $175.36 <----This is what I would like to get too.

Anyone know how to get to this? I know it may have something to do with weights and such, but the settings for those just seem to be so spread out all over the place when using these contrib mods.

Any thoughts, ideas or suggestions would be much appreciated.

TIA,
txcrew

zmove's picture
Offline
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.Internationalizationizer
Joined: 08/13/2007
Juice: 1192
Re: Discounts and line items

Yes, it's true that it should be like you say.

For the implementation, I think it should be a new parameter in hook_line_item() function.

to take the example in the function API :

<?php
function uc_order_line_item() {
 
$items[] = array(
   
'id' => 'generic',
   
'title' => t('Empty Line'),
   
'weight' => 2,
   
'default' => FALSE,
   
'stored' => TRUE,
   
'add_list' => TRUE,
   
'calculated' => TRUE,
   
'callback' => 'uc_line_item_generic',
   
'subtotal' => TRUE, // See this new line that allow to choose iif you want to show a subtotal before adding the line item.
 
);
?>

like that, each module developper should easily choose if they want or need a subtotal before the line item their module add. And it would avoid developpers to generate bugs by calling a strong core fully tested feature instead of coding their little routine each time you need to do that.

I know that the core tax module show a subtotal excluding tax before adding the tax amount, maybe it could be a good begining to look how it was done.

txcrew's picture
Offline
Joined: 09/28/2007
Juice: 103
Re: Re: Discounts and line items

Thanks for the reply, zmove.

I checked out what you said and thought I would be able to make some sense of it. But really, it seems to be way over my head as I don't really understand the development side of things. It looks like there are a few different functions here and workflow_ng integration which really scared me off of attempting this myself.

Here is where I started

<?php /**
* Update and save tax line items to the order.
*/
function uc_taxes_order($op, $arg1, $arg2) {
  switch (
$op) {
    case
'save':
     
$changes = array();
     
$line_items = uc_line_item_tax('load', $arg1);
     
//$arg1->line_items = uc_order_load_line_items($arg1, true);
     
if (is_array($arg1->line_items)) {
       
//drupal_set_message('<pre>'. var_export($arg1->line_items, true) .'</pre>');
       
foreach ($arg1->line_items as $line) {
          if (
$line['type'] == 'tax') {
           
$delete = true;
            foreach (
$line_items as $id => $new_line) {
              if (
$new_line['title'] == $line['title']) {
                if (
$new_line['amount'] != $line['amount']) {
                 
uc_order_update_line_item($line['line_item_id'], $new_line['title'], $new_line['amount']);
                 
$changes[] = t('Changed %title to %amount.', array('%amount' => uc_currency_format($new_line['amount']), '%title' => $new_line['title']));
                }
                unset(
$line_items[$id]);
               
$delete = false;
                break;
              }
            }
            if (
$delete) {
             
uc_order_delete_line_item($line['line_item_id']);
             
$changes[] = t('Removed %title.', array('%title' => $line['title']));
            }
          }
        }
      }
      if (
is_array($line_items)) {
        foreach (
$line_items as $line) {
         
uc_order_line_item_add($arg1->order_id, $line['id'], $line['title'], $line['amount'], $line['weight']);
         
$changes[] = t('Added %amount for %title.', array('%amount' => uc_currency_format($line['amount']), '%title' => $line['title']));
        }
      }
      if (
count($changes)) {
       
uc_order_log_changes($arg1->order_id, $changes);
      }
    break;
  }
}
?>

Is this even the place that you were talking about?

txcrew

zmove's picture
Offline
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.Internationalizationizer
Joined: 08/13/2007
Juice: 1192
Re: Discounts and line items

Sorry, I say something wrong in my previous post, in fact this possibilities is already provided but differently.

If you look through the tax module code, in the hook_line_item function you can see :

<?php
/**
* Implementation of Übercart's hook_line_item().
*/
function uc_taxes_line_item() {
 
$items[] = array(
   
'id' => 'tax',
   
'title' => t('Tax'),
   
'callback' => 'uc_line_item_tax',
   
'weight' => 9,
   
'stored' => true,
   
'default' => FALSE,
   
'calculated' => TRUE,
   
'display_only' => FALSE,
  );
 
$items[] = array(
   
'id' => 'tax_subtotal',
   
'title' => t('Subtotal excluding taxes'),
   
'callback' => 'uc_line_item_tax_subtotal',
   
'weight' => 8,
   
'stored' => false,
   
'calculated' => false,
  );

  return

$items;
}
?>

Instead of putting a "subtotal" parameter, you can just add a value in the $item[] array. Each element of the array can have a callback function, so you can look through the uc_line_item_tax_subtotal() function and you will see how subtotal is implemented in the tax module.

Then you can take example on this code to implement it in your discount module.

txcrew's picture
Offline
Joined: 09/28/2007
Juice: 103
Re: Re: Discounts and line items

I see what you are getting at.

This is where I am at:

<?php {

           

$coupon_result->message = t('Coupon code success : ');
           
$coupon_result->code = $coupon_data->code;
           
$coupon_result->cid = $coupon_data->cid;
           
$coupon_result->weight = $coupon_data->weight;   

           

// Calculate the discount amount
           
switch($coupon_data->type) {
                case
'percentage':
               
$coupon_result->amount = $total * $coupon_data->value / 100;
                break;
                case
'price':
                   
$coupon_result->amount = $coupon_data->value;
                break;
        }
        return
$coupon_result;
?>

Could I just add something like 'callback' => '$order_total' to $coupon_result->amount = $total * $coupon_data->value / 100;

or is there another ubercart variable in which I can call the original subtotal?

zmove's picture
Offline
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.Internationalizationizer
Joined: 08/13/2007
Juice: 1192
Hi, When you look in the

Hi,

When you look in the uc_taxes modules, in the uc_line_item_tax_subtotal() function, you can see this code :

<?php
function uc_line_item_tax_subtotal($op, $order) {
 
$amount = 0;
  if (
is_array($order->products)) {
    foreach(
$order->products as $item){
     
$amount += $item->price * $item->qty;
    }
  }
  if (
is_array($order->line_items)){
    foreach (
$order->line_items as $key => $line_item){
      if (
substr($line_item['type'], 0, 3) != 'tax'){
       
$amount += $line_item['amount'];
       
$different = true;
      }
      else{
       
$has_taxes = true;
      }
    }
  }
  if (
is_array($order->taxes)){
   
$has_taxes = true;
  }
  if (
$different && $has_taxes){
    switch (
$op){
      case
'cart-preview':
       
drupal_add_js("\$(document).ready(function(){
          if (window.set_line_item){
            set_line_item('tax_subtotal', '"
. t('Subtotal excluding taxes') ."', ". $amount .", ". variable_get('uc_li_tax_subtotal_weight', 8) .");
          }
        });"
, 'inline');
      break;
      case
'load':
        return array(array(
         
'id' => 'tax_subtotal',
         
'title' => t('Subtotal excluding taxes'),
         
'amount' => $amount,
         
'weight' => variable_get('uc_li_tax_subtotal_weight', 8),
        ));
    }
  }
}
?>

It seems that, to get the subtotal before applying the tax, the module have to make the calculation from the begining.

So it calculate the subtotal for products in the cart :

<?php
  $amount
= 0;
  if (
is_array($order->products)) {
    foreach(
$order->products as $item){
     
$amount += $item->price * $item->qty;
    }
  }
?>

And then it add all the prices for previous line items

<?php
   
foreach ($order->line_items as $key => $line_item){
      if (
substr($line_item['type'], 0, 3) != 'tax'){
       
$amount += $line_item['amount'];
       
$different = true;
      }
     ...
?>

Don't have lot of time to study this code, but the idea is here. The things I don't understand is that the line items that have 'display_only' to TRUE or 'calculated' to FALSE (I never remember the difference between both) should not enter in the calculation. And in the code, I don't see how it's done..?

So you will need to do something similar for the coupon module to add a subtotal before applying the coupon.

txcrew's picture
Offline
Joined: 09/28/2007
Juice: 103
Got it. I will give it a

Got it.

I will give it a spin and let you know how it goes.

Thanks much for all the help!

txcrew

txcrew's picture
Offline
Joined: 09/28/2007
Juice: 103
Re: Discounts and line items

Added $75 bounty via paypal to anyone who can figure this out for me.