fix: calculate value correctly when P amounts have few decimal digits [#2254]
Valuation in another commoditay could sometimes be inaccurate if the P price amounts did not have enough decimal places.
This commit is contained in:
parent
4e6f6611a6
commit
21a84fb336
@ -48,7 +48,8 @@ import Hledger.Data.Types
|
|||||||
import Hledger.Data.Amount
|
import Hledger.Data.Amount
|
||||||
import Hledger.Data.Dates (nulldate)
|
import Hledger.Data.Dates (nulldate)
|
||||||
import Text.Printf (printf)
|
import Text.Printf (printf)
|
||||||
import Data.Decimal (decimalPlaces, roundTo)
|
import Data.Decimal (decimalPlaces, roundTo, Decimal)
|
||||||
|
import Data.Word (Word8)
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
@ -290,12 +291,17 @@ priceLookup makepricegraph d from mto =
|
|||||||
-- aggregate all the prices into one
|
-- aggregate all the prices into one
|
||||||
product rates
|
product rates
|
||||||
-- product (Decimal's Num instance) normalises, stripping trailing zeros.
|
-- product (Decimal's Num instance) normalises, stripping trailing zeros.
|
||||||
-- Here we undo that (by restoring the old max precision with roundTo),
|
-- But we want to preserve even those, since the number of decimal digits
|
||||||
-- so that amountValueAtDate can see the original internal precision,
|
-- here will guide amountValueAtDate in setting the Amount display precision later.
|
||||||
-- to use as the display precision of calculated value amounts.
|
-- So we restore them. Or rather, we ensure as many decimal digits as the maximum seen among rates.
|
||||||
-- (This can add more than the original number of trailing zeros to some prices,
|
-- (Some prices might end up more precise than they were, but that seems harmless here.)
|
||||||
-- making them seem more precise than they were, but it seems harmless here.)
|
& setMinDecimalPlaces (maximum $ map decimalPlaces rates)
|
||||||
& roundTo (maximum $ map decimalPlaces rates)
|
|
||||||
|
-- Ensure this Decimal has at least this many decimal places, adding trailing zeros if necessary.
|
||||||
|
setMinDecimalPlaces :: Word8 -> Decimal -> Decimal
|
||||||
|
setMinDecimalPlaces n d
|
||||||
|
| decimalPlaces d < n = roundTo n d -- too few, add some zeros
|
||||||
|
| otherwise = d -- more than enough, keep as-is
|
||||||
|
|
||||||
tests_priceLookup =
|
tests_priceLookup =
|
||||||
let
|
let
|
||||||
|
|||||||
@ -341,3 +341,18 @@ Balance changes in 2019, valued at period ends:
|
|||||||
==========++========
|
==========++========
|
||||||
Assets:A || $2.00
|
Assets:A || $2.00
|
||||||
Income:B || $-2.00
|
Income:B || $-2.00
|
||||||
|
|
||||||
|
# ** 33. #2254 Conversion rates should not be display-rounded during value calculation.
|
||||||
|
# 100 * 10.5 * 100.5 = 105525
|
||||||
|
<
|
||||||
|
P 2000-01-01 A 10.5 B
|
||||||
|
P 2000-01-01 B 100.5 C
|
||||||
|
|
||||||
|
2000-01-01
|
||||||
|
(a) 100 A
|
||||||
|
|
||||||
|
$ hledger -f- print -X C
|
||||||
|
2000-01-01
|
||||||
|
(a) 105525 C
|
||||||
|
|
||||||
|
>=
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user