Hi all!
I report this bug here since I didn't find it nor here, nor in the Ubercart.org issue queue.
Problem reported here : http://www.ubercart.org/forum/support/6817/strange_behaviour_order_previ...
And here : http://www.ubercart.org/forum/support/7169/uc_taxes_drives_me_crazy
This is a copy/paste from my support forum request (link above).
I'm on Drupal 5.12, Ubercart 1.5 and everyt single module is up to date.
What I'm doing on a fresh install of D5 + Ubercart 1.5 :
- create 1 product
- set a taxes rule 19,6% on products and shipping (or only on products, it's the same result)
- set 3 different flatrate methods, different name, price, etc.
From here :
- put the product on your cart, go to checkout
- click on the "click to calculate shipping" button
- then switch between the 3 different shipping methods
If you watch carefully the preview pane, the taxes line item dis/appear mostly on 1 out of 2 clicks.
I'm pretty sure it comes from something in uc_taxes.module in the function uc_taxes_javascript().
Because here what I did to test :
function uc_taxes_javascript() {
drupal_set_header("Content-Type: text/javascript; charset=utf-8");
$order = unserialize($_POST['order']);
// if ($order = unserialize(rawurldecode($order))) {
$taxes = module_invoke_all('calculate_tax', $order);
// $subtotal = uc_line_item_tax_subtotal('load', $order);
// if (is_array($subtotal) && !empty($taxes)) {
// $taxes['subtotal'] = array('id' => 'subtotal', 'name' => $subtotal[0]['title'], 'amount' => $subtotal[0]['amount'], 'weight' => -10);
// }
// if (count($taxes)) {
// print drupal_to_js((array)$taxes);
// }
// else {
// print '{}';
// }
print_r($taxes);
// }
// else {
// print '{}';
// }
exit();
}
And Firebug ALWAYS shoes me my taxes rule, so what's the trick?
Oh really, really, I need you!!!
Thank you!
Jérémy
Comments
Comment #1
jchatard commentedOk, so I've just found what's going on.
It only happens if your tax rule title contains special characters, like in French : éàç, etc.
Why, all cart content on the checkout form is present in serialized way (from PHP) in input edit-cart-contents.
This is a good thing because any product containing specials chars is serialized this way :
So when it comes to function uc_taxes_javascript() (from uc_taxes.module) the unserialize call works great.
But, if you have extra line items in your checkout (shipping, taxes, etc.) which by definition ARE NOT in your cart, the function getTax() form uc_taxes.js creates a serialized version of your line items (tax included) by calling among other things :
If li_titles[key] stands for "aaaé", then li_titles[key].length will return 4, which is correct! But not true in PHP, because "é" is a multibyte character!
So it's logical that taxes calculation works 1 time out of 2.
The first you show the checkout page, taxes are present, so they are sent via JS with wrong (or right, you choose) string lenght. This causes unserialize to fail, so function returns {}.
The next time you, change, let say shipping quotes, the rule tax is not present, so the unserialize function fires right, and workflow-ng can apply the rule : you taxes rules are applied!
I've search way to manage multibytes strings via JS, but didn't find anything intersting. The other solution, would be to override the serialize/unserialize couple with function in the same spirit as :
But I don't know which is the best, and the quickiest way to solve that. For now, I fixed the problem by provide string with no special chars at all, but we should fix it.
Any help on this would be really appreciated!
Jérémy
Comment #2
jchatard commentedAfter, some more tests, it seems that the bug occurs also with any user submitted value on the checkout screen!
For example, my firstname : "Jérémy" cause the problem also. So no taxes displyed on the preview pane!
Comment #3
Island Usurper commentedOh, very well done. That's a very sticky problem to untangle.
I found a script to count the number of bytes in a string that works by encoding it first, and then replacing all of the %xx codes with "x". What's left is an ASCII string, whose length is equal to the number of bytes.
I've committed this change to the Bazaar repository, so you can expect this to be in 1.6.
(Ought to give credit where it's due: http://dt.in.th/2008-09-16.string-length-in-bytes.html is where I found the function.)
Comment #4
jchatard commentedYou've just saved my life!!
Thank you so much!
Jérémy
Comment #5
Anonymous (not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.