Forums / Contribution-Writing Guidelines / Obtaining a line-item (product) total after discounts

Obtaining a line-item (product) total after discounts

Started by retched on 27 May 2014, 11:38 PM · Views: 11,296

Results 1 to 14 of 14
27 May 2014, 11:38 PM
#1
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Obtaining a line-item (product) total after discounts

(Yes this could go to the TaxCloud thread but I figured this could be asked separately.)

Currently I'm working with a sales tax add-on that processes the items that I send to their server and then in return they send the total amount of sales tax back to me (my server).

What I noticed is that the orders are being sent with the total $products['final_total'] as the line-item total. A problem that I'm having is that the orders aren't being processed with any discounts applied to them. I would like to know if there is any way to go through an order and apply a discount as needed or where can I find the logic that does this currently within Zen-Cart?

6 Jun 2014, 4:42 AM
#2
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

Okay here's a better question, is there a better way to retrieve the $od_amount['total'] or rather the total amount of the discount from the active order? I know on the coupon module, the value is stored in the $od_amount['total'] variable. But I would like to know if there is a way to refer to this value (sans of assigning it to a variable in $_SESSION.

7 Jun 2014, 9:31 PM
#3
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: Obtaining a line-item (product) total after discounts

What about the part that sends the value to the taxer, using the difference between the two values provided that the final value is >= 0? Is that how it works/a possibility?

Stated because it sounds like you have found the two parts needed, the final price (before discounts) and the function/variable that contains the discount. Now would just need to send the desired taxable amount to be processed. Unless there is some other method of determination being searched?

ZC Installation/Maintenance Support <- Site
Contribution for contributions welcome...

7 Jun 2014, 9:33 PM
#4
mc12345678 avatar

mc12345678

Totally Zenned

Join Date:
Jul 2012
Posts:
16,908
Plugin Contributions:
2

Re: Obtaining a line-item (product) total after discounts

Alternatively, could modify the total price variable prior to going out and restore it upon return depending on what is trying to be attempted. I somewhat think it comes down to the desired math and how the data is used downstream of being collected/modified.

Another thing to consider that is often seen related to "coupons" is that the purchaser may still be responsible for the taxes before the discount is applied. Not sure if that aspect is locality dependent or. Just a way to cover ones bases. :)

ZC Installation/Maintenance Support <- Site
Contribution for contributions welcome...

10 Jun 2014, 4:59 AM
#5
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

mc12345678:

Alternatively, could modify the total price variable prior to going out and restore it upon return depending on what is trying to be attempted. I somewhat think it comes down to the desired math and how the data is used downstream of being collected/modified.

Another thing to consider that is often seen related to "coupons" is that the purchaser may still be responsible for the taxes before the discount is applied. Not sure if that aspect is locality dependent or. Just a way to cover ones bases. :)

That's essentially what I'm trying to do. The way the TaxCloud module works is that it takes the items from the cart to be processed (on a line by line basis) and processes it against their server. The server then returns a line by line tax total for each and the module on ZenCart tallies these and reports it back as a single line. I know where in the module the TaxCloud module where the module actually builds the XML to send via SOAP processing and I know the exact line of code where I can modify the total of the item.

So essentially what I have to do (or what I would like to do) is take the total amount of the discount, unless its a shipping-based discount, and divide the discount up into each of the line-item totals of the order as its being processed. This way the line-item gets processed with the discount applied against it. (As Sales Tax (at least in the US) has to be applied to the discount taxed line-item.)

So the walk through would be:

  • See if the $_SESSION['cc_id'] is not empty.
  • If it is empty, do nothing else. (There is no discount to apply.)
  • If it is not, then compute the discount or retrieve the amount of the discount from the order totals module and retrieve the ot_coupon's "value" property. Find the total number of items (or rather line-items) that exists in the order. Divide the discount into this amount and then apply it to the price being sent to the TaxCloud server being processed.

The only problem is, I don't know how to reproduce to call the functions that process coupons without applying the discount to all items, even those which I may not be applying the discount to.

Secondly, with regards to being due on tax for coupons, in my jurisdiction, the coupons are processed before determining the final total to be taxed.

10 Jun 2014, 2:58 PM
#6
wilt avatar

wilt

Oji-san

Join Date:
Jun 2003
Location:
Newcastle UK
Posts:
1,929
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

Hi.

Just wondering if you are over thinking things here.
Given I have no real knowledge of how Tax Cloud works.

However I would have expected Tax Cloud (while it may calculate final prices etc.) to return an effective tax rate for a given product
surely this is all you need then just let Zen Cart do the rest.

10 Jun 2014, 11:09 PM
#7
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

wilt:

Hi.

Just wondering if you are over thinking things here.
Given I have no real knowledge of how Tax Cloud works.

However I would have expected Tax Cloud (while it may calculate final prices etc.) to return an effective tax rate for a given product
surely this is all you need then just let Zen Cart do the rest.

That's the thing though, I would thought that TaxCloud would return proper tax rates and such, which it does. However using any coupons, particularly in my jurisdiction, causes me to collect too much sales tax at the time. I'm fine with return pennies and such but besides the fact that PayPal will outright lynch me and the additional fact that it would create reporting problems with TaxCloud, it's something I'd rather work outright.

11 Jun 2014, 12:16 AM
#8
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,515
Plugin Contributions:
176

Re: Obtaining a line-item (product) total after discounts

If I understand you correctly, I believe you said you're wanting to recalculate each line by pre-applying coupons before taxes.

  1. I'm mindful that some jurisdictions require merchants to assess tax on the sale price before applying discounts, so that the feds get as much tax money as possible. I just mention this not as a contradiction, but to encourage you to double-check your facts to be sure you're heading in the right direction.

  2. Are all your coupons "restricted to a specific product"? Or are all your coupons "applied to the entire shopping cart"? I ask because both cases require careful coding consideration. This is a pretty important component of what you're proposing.

  3. And of course you did mention casual awareness of the penny-rounding problems that will be created by applying discounts at a line-item level, thus requiring a complete recalculation of all totals and subtotals ... but your coding changes will need to take that into account too, else you won't be able to submit your order for payment if subtotals don't add up correctly.

.
Zen Cart - putting the dream of business ownership within reach of anyone!
Donate to: DrByte directly or to the Zen Cart team as a whole

Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.

11 Jun 2014, 6:29 PM
#9
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

DrByte:

If I understand you correctly, I believe you said you're wanting to recalculate each line by pre-applying coupons before taxes.

  1. I'm mindful that some jurisdictions require merchants to assess tax on the sale price before applying discounts, so that the feds get as much tax money as possible. I just mention this not as a contradiction, but to encourage you to double-check your facts to be sure you're heading in the right direction.

Well I completely understand that in some jurisdictions it must be noted that tax must be computed before AND after discounts are applied. However, I'm more or less trying to conform to the Developer Guidelines of the mod. According to the developer guide, since TaxCloud doesn't natively support discounts/promotions/etc., discounts have to be calculated on a pre-tax basis. I can't change the way their server computes it.

The way the calculation is done with the mod from Zencart:

  • Customer builds an order.
  • Customer approaches and lands on the checkout_payment page where an initial sales tax is to be computed.
  • TaxCloud will take the order of the customer, send it to the TaxCloud server, compute the tax on their server based on the information of the order and the settings of the account (where the customer is being billed, order is shipped to, and whether I elected to collect tax in that jurisdiction), send back to ZenCart the total amount of tax computer.
  • Customer then proceeds to enter a coupon code and/or select a payment method.
  • Customer confirms the order. TaxCloud will lock in that order and capture it for reporting purposes.

DrByte:

  1. Are all your coupons "restricted to a specific product"? Or are all your coupons "applied to the entire shopping cart"? I ask because both cases require careful coding consideration. This is a pretty important component of what you're proposing.

In my case, since I'm trying to modify their code to be a one-size fits all for everyone, the coupons type doesn't matter. If a coupon is made to affect a certain line or the entire order, I still have to take the entirety of the discount and divide it into the order OR find a way to make the discount calculation apply only to the line-item. The question I wrote regarding line-items makes it so that if a coupon is to affect ONE item, I have to calculate it for that ONE item. (It gets more complicated when I add in the fact that I have mods like table discounts to work this out with.)

DrByte:

  1. And of course you did mention casual awareness of the penny-rounding problems that will be created by applying discounts at a line-item level, thus requiring a complete recalculation of all totals and subtotals ... but your coding changes will need to take that into account too, else you won't be able to submit your order for payment if subtotals don't add up correctly.

I was under the assumption that the native discount coupon in ZenCart does that. In short, I should only be affecting just the calculation of the TaxCloud's order_total entry and nothing else.

11 Jun 2014, 6:57 PM
#10
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

By the way, I've done the research on my jurisdiction (New York) and it is indeed true that sales tax must be calculated on the total AFTER the discount is removed.

11 Jun 2014, 9:09 PM
#11
lhungil avatar

lhungil

Totally Zenned

Join Date:
Feb 2012
Location:
mostly harmless
Posts:
1,818
Plugin Contributions:
4

Re: Obtaining a line-item (product) total after discounts

Clarification:
It sounds like you are currently using an "order total" module to apply discounts against the entire order. This means the customer pays the advertised price for the products and tax on the advertised price. Afterwards you are applying a discount to the customer's order.

It also sounds like you would prefer to apply the discount directly to the products. The business need is to not charge tax on the advertised price, but instead upon the actual price paid for the product.

The 3rd party "tax system" you are using does calculations based upon line items (product and order). Most likely to accommodate the myriad tax rules which may apply. The 3rd party "tax system" also has no way to know what line item (product or order) a discount line should be applied against. Because of this, it is not taking into consideration any "negative" line items (probably as it does not know what to do with them if mixed tax rates may apply to various line items).

Are these accurate?

Question:
In addition to coupons, what other discount methods are you using?

Background:
I believe most (if not all) of the current "order total" modules for Zen Cart apply the discount only at the "order" level. Most of these can (if enabled) directly modify the tax amounts generated by "ot_tax" to apply tax only to the discounted price.

Internally, Zen Cart sales and specials are applied on a product level (and reflected in "final_price").

Another Potential Solution:
Code a new (or recode an existing) "order total" module to calculate and apply the discounts directly to the products. Then change the sort_order to occur before tax is calculated by the 3rd party tax module.

If a discount is applied based upon multiple products the code would need to account for HOW the discount should be applied. Would it be to just one of the products? Equal discount to all products? Different discount amounts per product? I am guessing this is just a small part of what DrByte was hinting at (item 2).

Note 1: This was the first solution which entered my mind (there probably are some alternatives). This solution not only can handle discounts known in advance, but also discounts such as coupons applied during checkout. It also avoids needing to modify the core Zen Cart code to accommodate how prices are calculated. However it will probably require some math and an in-depth understanding of the shopping_cart class and order_total modules.

Note 2: It may be worth asking the 3rd party tax service if they have a way to pass "discounts" to their service and let them handle figuring out taxes to ensure taxes are calculated correctly in all jurisdictions which may apply.

The glass is not half full. The glass is not half empty. The glass is simply too big!
Where are the Zen Cart Debug Logs? Where are the HTTP 500 / Server Error Logs?
Zen Cart related projects maintained by lhûngîl : Plugin / Module Tracker

17 Jun 2014, 8:05 PM
#12
retched avatar

retched

Totally Zenned

Join Date:
Jun 2007
Location:
Bronx, New York, United States
Posts:
949
Plugin Contributions:
3

Re: Obtaining a line-item (product) total after discounts

lhungil:

Clarification:
It sounds like you are currently using an "order total" module to apply discounts against the entire order. This means the customer pays the advertised price for the products and tax on the advertised price. Afterwards you are applying a discount to the customer's order.

It also sounds like you would prefer to apply the discount directly to the products. The business need is to not charge tax on the advertised price, but instead upon the actual price paid for the product.

lhungil:

The 3rd party "tax system" you are using does calculations based upon line items (product and order). Most likely to accommodate the myriad tax rules which may apply. The 3rd party "tax system" also has no way to know what line item (product or order) a discount line should be applied against. Because of this, it is not taking into consideration any "negative" line items (probably as it does not know what to do with them if mixed tax rates may apply to various line items).

Are these accurate?

Correct in all regards. A system limitation of the suite is that you cannot try to process a negative price or Qty through it to perform a discount. Instead, as per their recommendation, the discount needs to be divided across the board to all items. In my case, I'd rather not apply the discount divided into all the items of the order but rather just the line items where the discount applies (if any).

lhungil:

Question:
In addition to coupons, what other discount methods are you using?

There are three discount modules being run: the discount coupons provided with ZenCart, the Rewards Point Suite (there is a percentage discount), and the mod "Table Discounts"

lhungil:

Background:
I believe most (if not all) of the current "order total" modules for Zen Cart apply the discount only at the "order" level. Most of these can (if enabled) directly modify the tax amounts generated by "ot_tax" to apply tax only to the discounted price.

Internally, Zen Cart sales and specials are applied on a product level (and reflected in "final_price").

I looked into the "final_price" of the Cart class. It does work with sales and specials but not so much coupons which is where I'm having the problem with.

lhungil:

Another Potential Solution:
Code a new (or recode an existing) "order total" module to calculate and apply the discounts directly to the products. Then change the sort_order to occur before tax is calculated by the 3rd party tax module.

If a discount is applied based upon multiple products the code would need to account for HOW the discount should be applied. Would it be to just one of the products? Equal discount to all products? Different discount amounts per product? I am guessing this is just a small part of what DrByte was hinting at (item 2).

I ended up going with the equal discount to all products method instead. I'm not trying to find a way instead of the $_SESSION method. I tried to do this with a homebrewed add-on on to the cart object but I don't know how to pass back the value so that its being modified and updated.

lhungil:

Note 1: This was the first solution which entered my mind (there probably are some alternatives). This solution not only can handle discounts known in advance, but also discounts such as coupons applied during checkout. It also avoids needing to modify the core Zen Cart code to accommodate how prices are calculated. However it will probably require some math and an in-depth understanding of the shopping_cart class and order_total modules.

Note 2: It may be worth asking the 3rd party tax service if they have a way to pass "discounts" to their service and let them handle figuring out taxes to ensure taxes are calculated correctly in all jurisdictions which may apply.

In regards to note 2: Unfortunately there is no current way with the tax service to accept discounts. It was in fact their own advice to take the discount and divide it up into all of the lines. I did this by tallying up all the discounts over each of the modules, adding it back to a $_SESSION['order_discounts'] which I unset when the order is completed. Then I totaled up all the Qty's in a cart and made an average, applying that back onto the unit price.

        $qtyCart = 0;        
        $discountperitem = 0;


        foreach ($products as $k => $product) {
            $qtyCart += $product['qty'];
        }




        $total_discount = 0;


        if(is_array($_SESSION['order_discount'])) {
            foreach ($_SESSION['order_discount'] as $ot_discount) {
                $total_discount += $ot_discount["value"];
            }
        }


        $total_discount += $_SESSION["cot_gv"];


        $discountperitem = ($total_discount) / $qtyCart;

That was in general the best I could do with the situation. This actually works with PayPal and such, so I guess it works. The only thing that worries me about this is if a cart has a taxable and a non-taxable item at the same time.

16 Feb 2015, 1:58 AM
#13
mega_moonshine avatar

mega_moonshine

New Zenner

Join Date:
May 2009
Location:
North Las Vegas, NV
Posts:
44
Plugin Contributions:
0

Re: Obtaining a line-item (product) total after discounts

While not exactly trying to do the same, it is similar enough to what I want to be able to do, which is to calculate and adjust the freeoptions shipping module to base the free shipping on Cart Total AFTER the discounts are applied, not before.

To do that, I had to figure out a way to get the amount (of the total discount) per discount module (ot_coupon.php) and for the added mod plugin I installed, newsletter discount (ot_newsletter_discount.php) found in the includes/modules/order_total directory.

Any other discount mods you may have installed should be located here as well. You will need to figure out what is the best method to determine if the discount is active or not. That is why I have the IF - ELSE statements.

No explanation is necessary if you understand the code below. It works. You just need to figure out where to put it and use it for your purposes. I'm on a tight schedule and when I have more time, I may expand on it further. Or not, lol.

// added this for calculating Adjusted Total AFTER Discounts to base free shipping on,
// instead of free shipping based on total BEFORE discounts!

if (isset($_SESSION['cc_id'])) {
    $coupon_total = $ot_coupon->calculate_deductions($_SESSION['cart']->show_total());
} else { $coupon_total['total'] = 0; }

if ($ot_newsletter_discount->is_subscriber()) {
    $nwsltr_total = $ot_newsletter_discount->calculate_deductions();
} else { $nwsltr_total['total'] = 0; }

$total_discounts = $coupon_total['total'] + $nwsltr_total['total'];
$adjusted_total = $_SESSION['cart']->show_total() - $total_discounts;

// echo 'Total Discounts = ' . $currencies->format($total_discounts) . '<br>';
// echo 'Adjusted Total = ' . $currencies->format($adjusted_total);
18 Feb 2015, 4:53 AM
#14
drbyte avatar

drbyte

Sensei

Join Date:
Jan 2004
Posts:
63,515
Plugin Contributions:
176

Re: Obtaining a line-item (product) total after discounts

.
Zen Cart - putting the dream of business ownership within reach of anyone!
Donate to: DrByte directly or to the Zen Cart team as a whole

Remember: Any code suggestions you see here are merely suggestions. You assume full responsibility for your use of any such suggestions, including any impact ANY alterations you make to your site may have on your PCI compliance.
Furthermore, any advice you see here about PCI matters is merely an opinion, and should not be relied upon as "official". Official PCI information should be obtained from the PCI Security Council directly or from one of their authorized Assessors.