Attached patch takes advantage of the decimals and rounding property defined in the currency definition array.

The patch extends the default currency formatter commerce_currency_format to use a customized rounding function.

The new function not only respects the decimals but also the rounding steps. E.g. Swiss Francs are rounded using 0.05 steps.

If someone knows a smarter approach how to solve this - byte shifting? - feel free :D

Comments

rszrama’s picture

Component: Line item » Commerce

Thanks so much for the patch. I made some minor changes in the name of the function and in that I'm passing in the currency object instead of two separate parameters. I also updated the default currencies array to not include the rounding property any more but just to default that to 0. (And for readability, I changed that property from rounding to rounding_step to conform to the docs. I wonder, too, if "decimals" shouldn't be changed to "precision".)

There were a couple other places that needed to use the commerce_currency_round() function (two Views handlers), though I left the number_format() alone in commerce_price.module with the minor change of loading the currency object and using its actual number of decimals (this was a long-standing TODO item in the comments).

Please let me know if I missed anything or introduced a regression. ; )

I am wondering - should currencies that use the .5 and .2 rounding step also specify decimals => 1? Would you display prices as 95.5 CHF or 95.50 CHF? And I don't see any currencies specifying a 2 for the rounding step... should there be?

Commit: https://github.com/rszrama/drupalcommerce/commit/ea315258cbfa2ea4a317848...

das-peter’s picture

Just merged - awesome how fast you are with integrating patches :)

I'll let you know if I come across any regression.

Right now the assumption of the rounding function is, that always the last decimal position has to be rounded to the rounding_step - this code handles that $currency->rounding_step / pow(10, $currency->decimals). Means a combination like rounding_step 5, decimals 2 generates e.g. 10.45, but if the decimals is set to 1 it would generate 10.5.
We could change this to make it decimals independent by defining rounding_step as decimal instead an integer (E.g. 0.05 for Swiss Francs). This could also lead to a small performance gain, since we could reduce the calculation steps for the $modifier.

Frankly speaking I don't know any other currency besides Swiss Francs that has this kind of special rounding. Nevertheless I tried to keep the code as general as possible, just in case... :)

das-peter’s picture

Attached patch contains:

  • Changed rounding_step format to a decimal representation. Attention: Needs to be defined as string to avoid unpredictable rounding results
  • Modified commerce_currency_round to work with the new property format
  • Modified SimpleTests to work with the new property format
  • Currency caching is now language dependent.
  • Modified function documentations and added commerce.api.php with a detailed description of the currency array. Please review, I doubt that my English is really usable for proper documentation :)
rszrama’s picture

Status: Needs review » Fixed

Appears to work just fine, and you read my mind with the language specific caching. : D

Status: Fixed » Closed (fixed)

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