Skip to content

Rounding strategies and decimal place pricing #695

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
RaederDev opened this issue Feb 7, 2019 · 12 comments
Closed

Rounding strategies and decimal place pricing #695

RaederDev opened this issue Feb 7, 2019 · 12 comments
Labels
💡 enhancement Ideas and suggestions 🧾 orders

Comments

@RaederDev
Copy link

Description

Commerce incorrectly adds 1-2c to our order total even though it shouldn't.

Steps to reproduce

  1. Create products with the following prices:
    Luftpolsterfolie (4.917 EUR)
    Klebeband (1.667 EUR)
    BOX (3.75 EUR)
    Reisekoffer (8.25 EUR)
    Business-Trolley (5.75 EUR)
    Golftasche (12.417 EUR)

  2. Add a 20%, not included in price VAT tax rate.

  3. Add products to cart:
    3x BOX
    1x Reisekoffer
    1x Business-Trolley
    1x Golftasche
    1x Klebeband
    1x Luftpolsterfolie

  4. Your cart.totalPrice will now be € 53.11 even though it should be € 53.10.
    Because ((3.75 * 3) + 8.25 + 12.417 + 5.75 + (1.667 + 4.917)) * 1.2 = 53.1012

Screenshots:
https://i.imgur.com/kW5OSKG.png
https://i.imgur.com/DNPB0zX.png

This is a very big issue for us. We are essentially overcharging clients 2c that we would need to refund leading to much more complications.

Additional info

  • Craft version: Craft Pro 3.1.8
  • PHP version: 7.2.13
  • Database driver & version: MySQL 5.5.5
  • Plugins & versions: Craft Commerce | 2.0.4, Stripe for Craft Commerce 1.0.10
@ccchapman
Copy link

ccchapman commented Feb 7, 2019

Your adjustments and line item totals seem to be correct in the screenshots. That makes me wonder if Currency::round() is causing this issue inside getTotalPrice().

return Currency::round($this->getItemSubTotal() + $this->getAdjustmentsTotal());

Recommend testing to see what the number is before and after it gets passed through that method.

Edit: It is the price for each line item being rounded causing this issue.

@RaederDev
Copy link
Author

With the help of @ccchapman I was able to track down the bug.
The problem is Line 407 in the LineItem model:

$this->salePrice = CurrencyHelper::round($this->saleAmount + $this->price);

salePrice is saved as a rounded value in the database before the tax adjuster gets a chance to produce a correct value. Rounding should be the last step not the first one.

If you change the line from
$this->salePrice = CurrencyHelper::round($this->saleAmount + $this->price);
to
$this->salePrice = $this->saleAmount + $this->price;
everything works correctly.

price field in database: 12.4170
salePrice field in database: 12.4200

@ccchapman
Copy link

ccchapman commented Feb 7, 2019

FWIW, the currency helper is rounding to two places for Euro per ISO 4217.

This issue aside, should purchasables even be allowed to have a price with decimals that differ from the standard they'll be rounded to? This seems misleading to show a currency with three decimal points in the CP when it will be rounded for line items.

@RaederDev
Copy link
Author

Yes you absolutely should be able to have prices with higher accuracy. We designed our prices in a way that they are mostly round numbers after tax has been applied. We'd still like to keep them without tax in the cms.

I understand that they need to be rounded once you send them to a payment gateway, but why round them before adjusters can be applied to them?

Or at least there should be an option to disable premature rounding if it's not a desired behavior

@lukeholder lukeholder added the 💡 enhancement Ideas and suggestions label Mar 13, 2019
@lukeholder lukeholder added this to the 2.2 milestone Mar 13, 2019
@lukeholder lukeholder self-assigned this Aug 29, 2019
@lukeholder lukeholder changed the title Incorrect rounding of decimal places in final price Rounding strategies and decimal place pricing Oct 10, 2019
@lukeholder lukeholder removed their assignment Nov 11, 2019
@lukeholder lukeholder modified the milestones: 3.0, 3.x, 3.1 Feb 6, 2020
@nfourtythree
Copy link
Contributor

For anyone following this, we have pushed some updates to rounding on subtotals, discounts and tax to the 3.1 branch and it would be great to get some feedback to see if this is what people expect.

You can install this version with the following requirement:

"require": {
  "craftcms/commerce": "3.1.x-dev",
  "...": "..."
},
"minimum-stability": "dev"

Feedback on this would be greatly appreciated.

@nfourtythree nfourtythree modified the milestones: 3.1, Backlog Apr 1, 2020
@aladrach
Copy link

Since this update, a plugin I've developed that relies on the previous order of rounding has been broken. Is there an easy way for me to override this behavior?

@kswilliames
Copy link

Since this update we've been seeing overpayment of orders by a few cents, but only on orders with sale items. The rounding occurring on sale item price before the total outstanding balance calculation looks like it's responsible for the errors.

We're using CraftCMS 3.4.13 and Craft Commerce 3.1.1

@benlobach
Copy link

We've also noticed that the calculation on sale items does seem to be a bit high. On a $40 item where the sale is 25% off the product, we're seeing a discount of $10.005, rather than $10 even.

We're running Craft Commerce 3.1.3.

@aladrach
Copy link

aladrach commented May 8, 2020

Are there any updates on this? We can't update to the newest version until we have a workaround. Our client relies on half quantities, so we do some calculations on the backend, but the rounding strategy messes up our calculations.

@lukeholder
Copy link
Member

@benlobach Can not reproduce this with a discount.

Have a $40 item with 25% off discount and the amount is $10 flat

If you are talking about a %25 sale then this has been fixed for the next release of commerce due out soon. Fix is this line here: e0d8aa0#diff-212590035285ded558a7d6664e5a5a5fR385

@aladrach We do no support half quantities, so the change we made did not test for that use-case. Can you email support@craftcms.com and explain what you are doing and provide your use-case and examples. A database dump and examples of your custom code would also help.

@kswilliames we have emailed you about your paid amount rounding issue.

@lukeholder
Copy link
Member

If anyone comes here with a rounding issue (from a google search), please post and new issue with clear steps to reproduce. Thanks.

@hhentschel
Copy link

hhentschel commented Jun 4, 2022

While searching I'll keep coming back always to this issue, so i post it here:
basically it is still the same as here or here .
i would like to round item prices to 5 cents decimals, especially after discounts and sales being applied.
i also would like to round $itemSubTotal oder $cartTotal, but as i understand it, its not possible because there these option are only readable.

i tried it with an Order::EVENT_AFTER_SAVE to round the discount within a module, but i am using Sprig to change the quantity, which then does not round the discount.

I also tried to change the line items price with EVENT_POPULATE_LINE_ITEM but then the discounts and sales are not being applied anymore.
maybe i am doing something wrong with the order?

@lukeholder
How and when can i change/round the $itemPrice, after discounts and sales added?
Are there any new possibilities i have'nt found out yet?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💡 enhancement Ideas and suggestions 🧾 orders
Projects
None yet
Development

No branches or pull requests

8 participants