Problem/Motivation

I created a drupal e-commerce using Commerce Kickstarter (v. 7.x-1.10) profile on my local machine (Debian wheezy php 5.4.4-7) with Corporateclean theme.
Then i moved on the production machine (Debian squeeze php 5.3.3-7+squeeze14) performing few database search&replace (domain name changed, for example, but nothing about prices/amount/numberformat).
Now, in the production machine, the prices's amount get saved correctly in the database (integer, 2 decimal, e.g. 1499 for 14,99$), the problem comes when the prices are showed: looks like they pass throught a number_format function and for 14.99 i get 14.9900000000000002.

I used mymodule_form_commerce_product_ui_product_form_alter() to do some debug, and:
$form['commerce_price']['und'][0]['#entity']->commerce_price['und'][0]['amount'] = 1499
$form['commerce_price']['und'][0][amount]['#default_value'] = 14.9900000000000002

This is a big problem becose, for example, break down Paypal payment method (14.9900000000000002 is not a valid amount).

Another thing I noticed, is that the price doesnt show in the 'Add to Cart' form, but when the prices are showed to the user (in the cart, checkout page, order, etc..) they are all right: looks like this issue happen only when the amount is converted from integer to floating (e.g. when editing the product, when calculating the amounts for the payment method)

I tryed to reproduce the problem moving another site (that is very similar, same base-theme, same modules, same installation profile [kickstarter], same hosting's php settings, etc..) from the local machine to the production one, and again throught the search&replace db, but nothing, the problem does not happen again.

I havent made any "brute-force" edit to modules.

The theme (corporateclean) doesnt have theming funciton about prices/amounts, neither do my custom module (that i tryed to disable too)
I tryed both with and w/ taxes.
I dont have custom pricing rules (by the way, this problem happen even in the product's edit page, so nothing to do with pricing rules).

I really dont know how to debug further; Where can i look to see why is this happening?

p.s: i know that testing and deployng on different machines with different SO and php version is really a bad practice, but this is what the company gave me -.-

Comments

Issue summary:View changes

added info

Category:bug» support
Status:Active» Postponed (maintainer needs more info)

We'll need to track this down further before we know if it's a problem in Commerce itself; I honestly haven't seen any floating point errors in a long time, thanks at least in some part to our integer based price amount storage. You're saying there was nothing at all interacting with the price fields on your site where you suddenly got the additional decimal places? It just loaded that amount from the database and somehow converted it to render?

Yes, I've seen this thing the first time just after the migration on the production machine; In my development machine is still working right.

I confirm that neither CorporateClean (http://drupal.org/project/corporateclean) and my custom module (that I disabled too) do any manipulation on price/amount of entities.

This make me wonder about php version or libraries, that's why i migrated the second website.

I tryed a debug_backtrace(), and the problem appear inside drupal_build_form (the entity loaded before that function has amounts corrects, then inside drupal_build_form the floating decimals appears)... didnt find anything else usefull in the backtrace.

Now i try to switch-off all the modules i installed after the kickstart installation, if this fail too, I really dont know where to look.

The module i installed are:
captcha/
commerce_addressbook/
commerce_custom_line_items/
commerce_paypal/
commerce_vbo_views/
customizer <- my custom module
entity/
field_group/
i18n/
image_url_formatter/
imce/
imce_wysiwyg/
pathauto/
recaptcha/
references/
token/
variable/
views_bulk_operations/
wysiwyg/

Hmm, do you think i18n might be trying some sort of field translation?

My 2 cents were on i18n and custom_line_items, but disabling them didnt solve the problem.

The strange thing that now im focusing on, is the Add to cart form that doesnt show any price, maybe its related

It doesn't show a price on its own - that would come through product field injection (i.e. the price field from the product entity rendered into a view mode for the node that references it). Probably just a configuration thing; check the manage display tab for the node type and then for the product type to make sure it's visible in both places.

Sorry, I meant showing the price inside the add to cart block, but i saw that in the _working_ website i did this throught a module:

<?php
function dwork_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state){
   
// Add read only price field to add to cart form
   
if(isset($form_state['default_product']->commerce_price))
    {
       
$price = commerce_product_calculate_sell_price($form_state['default_product']);
       
$form['display_price'] = array(
           
'#title' => t('Price'),
           
'#type' => 'item',
           
'#markup' => commerce_currency_format($price['amount'], $price['currency_code']),
           
'#prefix' => '<div class="display-price">',
           
'#suffix' => '<span class="vat">vat included</span></div>',
        );
    }
}
?>

I can add the price as a stand-alone field and works as well (with price formatted correctly).

So the issue happen somewhere when the amount is taken from the database and converted into a float number (maybe for calculations?)
When the price is formatted in order to be shown to the user, the formatter correct this problem (number_format($n, 2, ',', "'") i suppose)

I would like to check the code where this happen, but can someone point me in what file is supposed to be that workflow?
Drupal Commerce is *big* ;)

commerce_currency_amount_to_decimal()

Version:7.x-1.3» 7.x-1.x-dev
Category:support» bug
Priority:Normal» Major
Status:Postponed (maintainer needs more info)» Active

The floating point error is totally expected. It does depend on the precision value in your php.ini:

<?php
$value
= 1499/100;
ini_set("precision", 19);
echo
$value; # Prints "14.99000000000000021"
ini_set("precision", 10);
echo
$value; # Prints "14.99"
?>

... but this should *not* affect number_format() in any way:

<?php
ini_set
("precision", 19);
echo
number_format($value, 2); # Prints "14.99"
?>

Everywhere we output a price, we should use number_format(). Every price displayed through commerce_currency_format() already does this, but we don't do this correctly in two places I could find:

  • commerce_price_field_widget_form() only runs number_format() if the resulting number doesn't already have a dot, which is incorrect
  • commerce_payment_order_transaction_add_form() don't use number_format() at all

There is one similar issue in Commerce Backoffice and one in Commerce Shipping. Commerce Jirafe has itself an implementation of the price that seems completely bogus (it uses the decimal and thousands separator of the currency while it is probably not valid).

From the original description of this issue, I also assume that there is a similar issue in Commerce Paypal.

Yeah, and probably Authorize.Net / CyberSource. I'd add to your list our "raw" price field formatter, as it's just check_plain()ing the item amount as loaded.

Wow that's wired!
Both sites has "precision = 18" both as master and local values (multihost), as you suggested i added

<?php
ini_set
("precision", 10);
?>

to drupal's index.php and worked like a charm.

But i still dont get why this happen only on the first site and not on the second one; The only thing that i can think of is some kind of settings stored in the database, becose everythings else is identical.

I'll try to look the functions you mentioned further to get the point.

Thanks for now guys, I'll come back soon (i hope) with news.

Priority:Major» Normal
Status:Active» Fixed

Finally got around to getting the fix in here. I decided not to make the fix for the raw price formatter, as it's supposedly rendering an integer amount as pulled from the database. I could apply a number_format() to it, but that would be the same as a round(), and I'm not sure that's helpful... besides, it's not likely used very often and is even less likely to have had arithmetic performed on it. I can always reconsider.

However, there was an additional place in Rules since this issue was opened where we were rendering a default amount value and didn't use number_format(). Since this issue we've also added commerce_paypal_price_amount() to the PayPal module to ensure prices were formatted to the proper decimal places. I'll look into my other payment modules and update them as need be.

Commit: http://drupalcode.org/project/commerce.git/commitdiff/514bea5

Status:Fixed» Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Issue summary:View changes

Added info