@@ -23,8 +23,9 @@ module Hledger.Data.Journal (
2323 addTransaction ,
2424 journalBalanceTransactions ,
2525 journalInferMarketPricesFromTransactions ,
26+ journalInferCommodityStyles ,
2627 journalApplyCommodityStyles ,
27- commodityStylesFromAmounts ,
28+ journalInferAndApplyCommodityStyles ,
2829 journalCommodityStyles ,
2930 journalToCost ,
3031 journalReverse ,
@@ -78,7 +79,6 @@ module Hledger.Data.Journal (
7879 journalEquityAccountQuery ,
7980 journalCashAccountQuery ,
8081 -- * Misc
81- canonicalStyleFrom ,
8282 nulljournal ,
8383 journalCheckBalanceAssertions ,
8484 journalNumberAndTieTransactions ,
@@ -87,7 +87,7 @@ module Hledger.Data.Journal (
8787 journalApplyAliases ,
8888 -- * Tests
8989 samplejournal ,
90- tests_Journal ,
90+ tests_Journal
9191)
9292where
9393
@@ -101,7 +101,7 @@ import Data.Function ((&))
101101import qualified Data.HashTable.Class as H (toList )
102102import qualified Data.HashTable.ST.Cuckoo as H
103103import Data.List (find , sortOn )
104- import Data.List.Extra (groupSort , nubSort )
104+ import Data.List.Extra (nubSort )
105105import qualified Data.Map as M
106106import Data.Maybe (catMaybes , fromJust , fromMaybe , isJust , mapMaybe )
107107#if !(MIN_VERSION_base(4,11,0))
@@ -627,7 +627,8 @@ journalModifyTransactions d j =
627627-- | Check any balance assertions in the journal and return an error message
628628-- if any of them fail (or if the transaction balancing they require fails).
629629journalCheckBalanceAssertions :: Journal -> Maybe String
630- journalCheckBalanceAssertions = either Just (const Nothing ) . journalBalanceTransactions True
630+ journalCheckBalanceAssertions = either Just (const Nothing ) . journalBalanceTransactions False True
631+ -- TODO: not using global display styles here, do we need to for BC ?
631632
632633-- "Transaction balancing", including: inferring missing amounts,
633634-- applying balance assignments, checking transaction balancedness,
@@ -722,18 +723,20 @@ updateTransactionB t = withRunningBalance $ \BalancingState{bsTransactions} ->
722723-- and (optional) all balance assertions pass. Or return an error message
723724-- (just the first error encountered).
724725--
725- -- Assumes journalInferCommodityStyles has been called, since those
726- -- affect transaction balancing.
726+ -- Assumes the journal amounts' display styles still have the original number
727+ -- of decimal places that was parsed (ie, display styles have not yet been normalised),
728+ -- since this affects transaction balancing.
727729--
728730-- This does multiple things at once because amount inferring, balance
729731-- assignments, balance assertions and posting dates are interdependent.
730- journalBalanceTransactions :: Bool -> Journal -> Either String Journal
731- journalBalanceTransactions assrt j' =
732+ --
733+ journalBalanceTransactions :: Bool -> Bool -> Journal -> Either String Journal
734+ journalBalanceTransactions usedisplaystyles assrt j' =
732735 let
733736 -- ensure transactions are numbered, so we can store them by number
734737 j@ Journal {jtxns= ts} = journalNumberTransactions j'
735738 -- display precisions used in balanced checking
736- styles = Just $ journalCommodityStyles j
739+ styles = if usedisplaystyles then Just $ journalCommodityStyles j else Nothing
737740 -- balance assignments will not be allowed on these
738741 txnmodifieraccts = S. fromList $ map paccount $ concatMap tmpostingrules $ jtxnmodifiers j
739742 in
@@ -965,25 +968,66 @@ checkBalanceAssignmentUnassignableAccountB p = do
965968
966969--
967970
971+ -- | Get an ordered list of amounts in this journal which can
972+ -- influence canonical amount display styles. Those are, in
973+ -- the following order:
974+ --
975+ -- * amounts in market price (P) directives (in parse order)
976+ -- * posting amounts in transactions (in parse order)
977+ -- * the amount in the final default commodity (D) directive
978+ --
979+ -- Transaction price amounts (posting amounts' aprice field) are not included.
980+ --
981+ journalStyleInfluencingAmounts :: Journal -> [Amount ]
982+ journalStyleInfluencingAmounts j =
983+ dbg7 " journalStyleInfluencingAmounts" $
984+ catMaybes $ concat [
985+ [mdefaultcommodityamt]
986+ ,map (Just . pdamount) $ jpricedirectives j
987+ ,map Just $ concatMap amounts $ map pamount $ journalPostings j
988+ ]
989+ where
990+ -- D's amount style isn't actually stored as an amount, make it into one
991+ mdefaultcommodityamt =
992+ case jparsedefaultcommodity j of
993+ Just (symbol,style) -> Just nullamt{acommodity= symbol,astyle= style}
994+ Nothing -> Nothing
995+
996+ -- | Infer commodity display styles for each commodity (see commodityStylesFromAmounts)
997+ -- based on the amounts in this journal (see journalStyleInfluencingAmounts),
998+ -- and save those inferred styles in the journal.
999+ -- Can return an error message eg if inconsistent number formats are found.
1000+ journalInferCommodityStyles :: Journal -> Either String Journal
1001+ journalInferCommodityStyles j =
1002+ case commodityStylesFromAmounts $ journalStyleInfluencingAmounts j of
1003+ Left e -> Left e
1004+ Right cs -> Right j{jinferredcommodities = dbg7 " journalInferCommodityStyles" cs}
1005+
1006+ -- | Apply the given commodity display styles to the posting amounts in this journal.
1007+ journalApplyCommodityStyles :: M. Map CommoditySymbol AmountStyle -> Journal -> Journal
1008+ journalApplyCommodityStyles styles j@ Journal {jtxns= ts, jpricedirectives= pds} =
1009+ j {jtxns= map fixtransaction ts
1010+ ,jpricedirectives= map fixpricedirective pds
1011+ }
1012+ where
1013+ fixtransaction t@ Transaction {tpostings= ps} = t{tpostings= map fixposting ps}
1014+ fixposting p = p{pamount= styleMixedAmount styles $ pamount p
1015+ ,pbalanceassertion= fixbalanceassertion <$> pbalanceassertion p}
1016+ -- balance assertion/assignment amounts, and price amounts, are always displayed
1017+ -- (eg by print) at full precision
1018+ fixbalanceassertion ba = ba{baamount= styleAmountExceptPrecision styles $ baamount ba}
1019+ fixpricedirective pd@ PriceDirective {pdamount= a} = pd{pdamount= styleAmountExceptPrecision styles a}
1020+
9681021-- | Choose and apply a consistent display style to the posting
9691022-- amounts in each commodity (see journalCommodityStyles).
9701023-- Can return an error message eg if inconsistent number formats are found.
971- journalApplyCommodityStyles :: Journal -> Either String Journal
972- journalApplyCommodityStyles j @ Journal {jtxns = ts, jpricedirectives = pds} =
1024+ journalInferAndApplyCommodityStyles :: Journal -> Either String Journal
1025+ journalInferAndApplyCommodityStyles j =
9731026 case journalInferCommodityStyles j of
9741027 Left e -> Left e
975- Right j' -> Right j' '
1028+ Right j' -> Right $ journalApplyCommodityStyles allstyles j '
9761029 where
977- styles = journalCommodityStyles j'
978- j'' = j'{jtxns= map fixtransaction ts
979- ,jpricedirectives= map fixpricedirective pds
980- }
981- fixtransaction t@ Transaction {tpostings= ps} = t{tpostings= map fixposting ps}
982- fixposting p = p{pamount= styleMixedAmount styles $ pamount p
983- ,pbalanceassertion= fixbalanceassertion <$> pbalanceassertion p}
984- -- balance assertion amounts are always displayed (by print) at full precision, per docs
985- fixbalanceassertion ba = ba{baamount= styleAmountExceptPrecision styles $ baamount ba}
986- fixpricedirective pd@ PriceDirective {pdamount= a} = pd{pdamount= styleAmountExceptPrecision styles a}
1030+ allstyles = journalCommodityStyles j'
9871031
9881032-- | Get the canonical amount styles for this journal, whether (in order of precedence):
9891033-- set globally in InputOpts,
@@ -1002,18 +1046,6 @@ journalCommodityStyles j =
10021046 defaultcommoditystyle = M. fromList $ catMaybes [jparsedefaultcommodity j]
10031047 inferredstyles = jinferredcommodities j
10041048
1005- -- | Collect and save inferred amount styles for each commodity based on
1006- -- the posting amounts in that commodity (excluding price amounts), ie:
1007- -- "the format of the first amount, adjusted to the highest precision of all amounts".
1008- -- Can return an error message eg if inconsistent number formats are found.
1009- journalInferCommodityStyles :: Journal -> Either String Journal
1010- journalInferCommodityStyles j =
1011- case
1012- commodityStylesFromAmounts $ journalStyleInfluencingAmounts j
1013- of
1014- Left e -> Left e
1015- Right cs -> Right j{jinferredcommodities = dbg7 " journalInferCommodityStyles" cs}
1016-
10171049-- -- | Apply this journal's historical price records to unpriced amounts where possible.
10181050-- journalApplyPriceDirectives :: Journal -> Journal
10191051-- journalApplyPriceDirectives j@Journal{jtxns=ts} = j{jtxns=map fixtransaction ts}
@@ -1242,7 +1274,7 @@ journalApplyAliases aliases j =
12421274-- liabilities:debts $1
12431275-- assets:bank:checking
12441276--
1245- Right samplejournal = journalBalanceTransactions False $
1277+ Right samplejournal = journalBalanceTransactions False False $
12461278 nulljournal
12471279 {jtxns = [
12481280 txnTieKnot $ Transaction {
@@ -1385,7 +1417,7 @@ tests_Journal = tests "Journal" [
13851417 ,tests " journalBalanceTransactions" [
13861418
13871419 test " balance-assignment" $ do
1388- let ej = journalBalanceTransactions True $
1420+ let ej = journalBalanceTransactions False True $
13891421 -- 2019/01/01
13901422 -- (a) = 1
13911423 nulljournal{ jtxns = [
@@ -1396,7 +1428,7 @@ tests_Journal = tests "Journal" [
13961428 (jtxns j & head & tpostings & head & pamount) @?= Mixed [num 1 ]
13971429
13981430 ,test " same-day-1" $ do
1399- assertRight $ journalBalanceTransactions True $
1431+ assertRight $ journalBalanceTransactions False True $
14001432 -- 2019/01/01
14011433 -- (a) = 1
14021434 -- 2019/01/01
@@ -1407,7 +1439,7 @@ tests_Journal = tests "Journal" [
14071439 ]}
14081440
14091441 ,test " same-day-2" $ do
1410- assertRight $ journalBalanceTransactions True $
1442+ assertRight $ journalBalanceTransactions False True $
14111443 -- 2019/01/01
14121444 -- (a) 2 = 2
14131445 -- 2019/01/01
@@ -1425,7 +1457,7 @@ tests_Journal = tests "Journal" [
14251457 ]}
14261458
14271459 ,test " out-of-order" $ do
1428- assertRight $ journalBalanceTransactions True $
1460+ assertRight $ journalBalanceTransactions False True $
14291461 -- 2019/1/2
14301462 -- (a) 1 = 2
14311463 -- 2019/1/1
0 commit comments