diff --git a/hledger-lib/Hledger/Data/TransactionModifier.hs b/hledger-lib/Hledger/Data/TransactionModifier.hs index e0b69fa13..18a7d511e 100644 --- a/hledger-lib/Hledger/Data/TransactionModifier.hs +++ b/hledger-lib/Hledger/Data/TransactionModifier.hs @@ -13,16 +13,17 @@ module Hledger.Data.TransactionModifier ( where import Control.Applicative ((<|>)) -import Data.Maybe +import Data.Maybe (catMaybes) import qualified Data.Text as T -import Data.Time.Calendar +import Data.Time.Calendar (Day) import Hledger.Data.Types import Hledger.Data.Dates import Hledger.Data.Amount -import Hledger.Data.Transaction -import Hledger.Query +import Hledger.Data.Transaction (txnTieKnot) +import Hledger.Query (Query, filterQuery, matchesAmount, matchesPosting, + parseQuery, queryIsSym, simplifyQuery) import Hledger.Data.Posting (commentJoin, commentAddTag) -import Hledger.Utils +import Hledger.Utils (dbg6, wrap) -- $setup -- >>> :set -XOverloadedStrings @@ -57,8 +58,8 @@ modifyTransactions d tmods ts = do -- Currently the only kind of modification possible is adding automated -- postings when certain other postings are present. -- --- >>> t = nulltransaction{tpostings=["ping" `post` usd 1]} -- >>> import qualified Data.Text.IO as T +-- >>> t = nulltransaction{tpostings=["ping" `post` usd 1]} -- >>> test = either putStr (T.putStr.showTransaction) . fmap ($ t) . transactionModifierToFunction nulldate -- >>> test $ TransactionModifier "" ["pong" `post` usd 2] -- 0000-01-01 @@ -79,7 +80,7 @@ transactionModifierToFunction :: Day -> TransactionModifier -> Either String (Tr transactionModifierToFunction refdate TransactionModifier{tmquerytxt, tmpostingrules} = do q <- simplifyQuery . fst <$> parseQuery refdate tmquerytxt let - fs = map (tmPostingRuleToFunction tmquerytxt) tmpostingrules + fs = map (tmPostingRuleToFunction q tmquerytxt) tmpostingrules generatePostings ps = [p' | p <- ps , p' <- if q `matchesPosting` p then p:[f p | f <- fs] else [p]] Right $ \t@(tpostings -> ps) -> txnTieKnot t{tpostings=generatePostings ps} @@ -92,8 +93,8 @@ transactionModifierToFunction refdate TransactionModifier{tmquerytxt, tmpostingr -- and a hidden _generated-posting: tag which does not. -- The TransactionModifier's query text is also provided, and saved -- as the tags' value. -tmPostingRuleToFunction :: T.Text -> TMPostingRule -> (Posting -> Posting) -tmPostingRuleToFunction querytxt pr = +tmPostingRuleToFunction :: Query -> T.Text -> TMPostingRule -> (Posting -> Posting) +tmPostingRuleToFunction query querytxt pr = \p -> renderPostingCommentDates $ pr { pdate = pdate pr <|> pdate p , pdate2 = pdate2 pr <|> pdate2 p @@ -105,13 +106,14 @@ tmPostingRuleToFunction querytxt pr = } where qry = "= " <> querytxt + symq = filterQuery queryIsSym query amount' = case postingRuleMultiplier pr of - Nothing -> const $ pamount pr + Nothing -> const . filterMixedAmount (symq `matchesAmount`) $ pamount pr Just n -> \p -> -- Multiply the old posting's amount by the posting rule's multiplier. let pramount = dbg6 "pramount" . head . amountsRaw $ pamount pr - matchedamount = dbg6 "matchedamount" $ pamount p + matchedamount = dbg6 "matchedamount" . filterMixedAmount (symq `matchesAmount`) $ pamount p -- Handle a matched amount with a total price carefully so as to keep the transaction balanced (#928). -- Approach 1: convert to a unit price and increase the display precision slightly -- Mixed as = dbg6 "multipliedamount" $ n `multiplyMixedAmount` mixedAmountTotalPriceToUnitPrice matchedamount diff --git a/hledger/test/journal/auto-postings.test b/hledger/test/journal/auto-postings.test index 000bfccfe..fa14cc18a 100644 --- a/hledger/test/journal/auto-postings.test +++ b/hledger/test/journal/auto-postings.test @@ -342,3 +342,22 @@ $ hledger -f- print --auto (b) 1.5 B ; generated-posting: = >=0 + +# 18. Auto-generated postings with currency matching only matches amounts with that currency in an auto posting (#1582) +< += assets cur:USD + (b:USD) *1 + +2017-12-14 + revenue:job -10 EUR + revenue:job -10 USD + assets + +$ hledger -f- print --auto +2017-12-14 ; modified: + revenue:job -10 EUR + revenue:job -10 USD + assets + (b:USD) 10 USD ; generated-posting: = assets cur:USD + +>=0