diff --git a/hledger-lib/Hledger/Data/PeriodicTransaction.hs b/hledger-lib/Hledger/Data/PeriodicTransaction.hs index 1b3dc2f1c..528960020 100644 --- a/hledger-lib/Hledger/Data/PeriodicTransaction.hs +++ b/hledger-lib/Hledger/Data/PeriodicTransaction.hs @@ -21,7 +21,7 @@ import Text.Printf import Hledger.Data.Types import Hledger.Data.Dates import Hledger.Data.Amount -import Hledger.Data.Posting (post) +import Hledger.Data.Posting (post, commentAddTagNextLine) import Hledger.Data.Transaction import Hledger.Utils.UTF8IOCompat (error') -- import Hledger.Utils.Debug @@ -69,6 +69,10 @@ instance Show PeriodicTransaction where -- | Generate transactions from 'PeriodicTransaction' within a 'DateSpan' -- -- Note that new transactions require 'txnTieKnot' post-processing. +-- The new transactions will have three tags added: +-- - a recur:PERIODICEXPR tag whose value is the generating periodic expression +-- - a generated-transaction: tag +-- - a hidden _generated-transaction: tag which does not appear in the comment. -- -- >>> _ptgen "monthly from 2017/1 to 2017/4" -- 2017/01/01 @@ -204,10 +208,14 @@ runPeriodicTransaction PeriodicTransaction{..} requestedspan = tstatus = ptstatus ,tcode = ptcode ,tdescription = ptdescription - ,tcomment = (if T.null ptcomment then "\n" else ptcomment) <> "recur: " <> ptperiodexpr - ,ttags = ("recur", ptperiodexpr) : pttags + ,tcomment = ptcomment + `commentAddTagNextLine` ("generated-transaction",period) + ,ttags = ("_generated-transaction",period) : + ("generated-transaction" ,period) : + pttags ,tpostings = ptpostings } + period = "~ " <> ptperiodexpr -- | Check that this date span begins at a boundary of this interval, -- or return an explanatory error message including the provided period expression diff --git a/hledger-lib/Hledger/Data/Posting.hs b/hledger-lib/Hledger/Data/Posting.hs index f67610502..66bbdbf45 100644 --- a/hledger-lib/Hledger/Data/Posting.hs +++ b/hledger-lib/Hledger/Data/Posting.hs @@ -54,6 +54,10 @@ module Hledger.Data.Posting ( concatAccountNames, accountNameApplyAliases, accountNameApplyAliasesMemo, + -- * comment/tag operations + commentJoin, + commentAddTag, + commentAddTagNextLine, -- * arithmetic sumPostings, -- * rendering @@ -356,6 +360,29 @@ postingValueAtDate prices styles mc d p = postingTransformAmount (mixedAmountVal postingTransformAmount :: (MixedAmount -> MixedAmount) -> Posting -> Posting postingTransformAmount f p@Posting{pamount=a} = p{pamount=f a} +-- | Join two parts of a comment, eg a tag and another tag, or a tag +-- and a non-tag, on a single line. Interpolates a comma and space +-- unless one of the parts is empty. +commentJoin :: Text -> Text -> Text +commentJoin c1 c2 + | T.null c1 = c2 + | T.null c2 = c1 + | otherwise = c1 <> ", " <> c2 + +-- | Add a tag to a comment, comma-separated from any prior content. +commentAddTag :: Text -> Tag -> Text +commentAddTag c (t,v) + | T.null c' = tag + | otherwise = c' `commentJoin` tag + where + c' = textchomp c + tag = t <> ":" <> v + +-- | Add a tag on its own line to a comment, preserving any prior content. +commentAddTagNextLine :: Text -> Tag -> Text +commentAddTagNextLine cmt (t,v) = + cmt <> if "\n" `T.isSuffixOf` cmt then "" else "\n" <> t <> ":" <> v + -- tests @@ -387,5 +414,14 @@ tests_Posting = tests "Posting" [ ,concatAccountNames ["a","(b)","[c:d]"] `is` "(a:b:c:d)" ] + ,tests "commentAddTag" [ + commentAddTag "" ("a","") `is` "a:" + ,commentAddTag "[1/2]" ("a","") `is` "[1/2], a:" + ] + + ,tests "commentAddTagNextLine" [ + commentAddTagNextLine "" ("a","") `is` "\na:" + ,commentAddTagNextLine "[1/2]" ("a","") `is` "[1/2]\na:" + ] ] diff --git a/hledger-lib/Hledger/Data/TransactionModifier.hs b/hledger-lib/Hledger/Data/TransactionModifier.hs index ddd7ef3f6..84103cef4 100644 --- a/hledger-lib/Hledger/Data/TransactionModifier.hs +++ b/hledger-lib/Hledger/Data/TransactionModifier.hs @@ -12,6 +12,7 @@ module Hledger.Data.TransactionModifier ( ) where +import Control.Applicative ((<|>)) import Data.Maybe #if !(MIN_VERSION_base(4,11,0)) import Data.Monoid ((<>)) @@ -23,6 +24,7 @@ import Hledger.Data.Dates import Hledger.Data.Amount import Hledger.Data.Transaction import Hledger.Query +import Hledger.Data.Posting (commentJoin, commentAddTag) import Hledger.Utils.UTF8IOCompat (error') import Hledger.Utils.Debug @@ -36,7 +38,15 @@ import Hledger.Utils.Debug modifyTransactions :: [TransactionModifier] -> [Transaction] -> [Transaction] modifyTransactions tmods = map applymods where - applymods = foldr (flip (.) . transactionModifierToFunction) id tmods + applymods t = taggedt' + where + t' = foldr (flip (.) . transactionModifierToFunction) id tmods t + taggedt' + -- PERF: compares txns to see if any modifier had an effect, inefficient ? + | t' /= t = t'{tcomment = tcomment t' `commentAddTag` ("modified","") + ,ttags = ("modified","") : ttags t' + } + | otherwise = t' -- | Converts a 'TransactionModifier' to a 'Transaction'-transforming function, -- which applies the modification(s) specified by the TransactionModifier. @@ -61,10 +71,10 @@ modifyTransactions tmods = map applymods -- transactionModifierToFunction :: TransactionModifier -> (Transaction -> Transaction) transactionModifierToFunction mt = - \t@(tpostings -> ps) -> txnTieKnot t{ tpostings=generatePostings ps } -- TODO add modifier txn comment/tags ? + \t@(tpostings -> ps) -> txnTieKnot t{ tpostings=generatePostings ps } where q = simplifyQuery $ tmParseQuery mt (error' "a transaction modifier's query cannot depend on current date") - mods = map tmPostingRuleToFunction $ tmpostingrules mt + mods = map (tmPostingRuleToFunction (tmquerytxt mt)) $ tmpostingrules mt generatePostings ps = [p' | p <- ps , p' <- if q `matchesPosting` p then p:[ m p | m <- mods] else [p]] @@ -86,14 +96,23 @@ tmParseQuery mt = fst . flip parseQuery (tmquerytxt mt) -- which will be used to make a new posting based on the old one (an "automated posting"). -- The new posting's amount can optionally be the old posting's amount multiplied by a constant. -- If the old posting had a total-priced amount, the new posting's multiplied amount will be unit-priced. -tmPostingRuleToFunction :: TMPostingRule -> (Posting -> Posting) -tmPostingRuleToFunction pr = +-- The new posting will have two tags added: a normal generated-posting: tag which also appears in the comment, +-- 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 = \p -> renderPostingCommentDates $ pr - { pdate = pdate p - , pdate2 = pdate2 p - , pamount = amount' p + { pdate = pdate pr <|> pdate p + , pdate2 = pdate2 pr <|> pdate2 p + , pamount = amount' p + , pcomment = pcomment pr `commentAddTag` ("generated-posting",qry) + , ptags = ("generated-posting", qry) : + ("_generated-posting",qry) : + ptags pr } where + qry = "= " <> querytxt amount' = case postingRuleMultiplier pr of Nothing -> const $ pamount pr Just n -> \p -> @@ -123,7 +142,7 @@ postingRuleMultiplier p = renderPostingCommentDates :: Posting -> Posting renderPostingCommentDates p = p { pcomment = comment' } where - datesComment = T.concat $ catMaybes [T.pack . showDate <$> pdate p, ("=" <>) . T.pack . showDate <$> pdate2 p] + dates = T.concat $ catMaybes [T.pack . showDate <$> pdate p, ("=" <>) . T.pack . showDate <$> pdate2 p] comment' - | T.null datesComment = pcomment p - | otherwise = T.intercalate "\n" $ filter (not . T.null) [T.strip $ pcomment p, "[" <> datesComment <> "]"] + | T.null dates = pcomment p + | otherwise = ("[" <> dates <> "]") `commentJoin` pcomment p diff --git a/hledger-lib/Hledger/Utils/Text.hs b/hledger-lib/Hledger/Utils/Text.hs index 42240c605..9ab432ca1 100644 --- a/hledger-lib/Hledger/Utils/Text.hs +++ b/hledger-lib/Hledger/Utils/Text.hs @@ -30,7 +30,7 @@ module Hledger.Utils.Text textstrip, textlstrip, textrstrip, - -- chomp, + textchomp, -- elideLeft, textElideRight, -- formatString, @@ -90,9 +90,9 @@ textlstrip = T.dropWhile (`elem` (" \t" :: String)) :: Text -> Text -- XXX isSpa textrstrip = T.reverse . textlstrip . T.reverse textrstrip :: Text -> Text --- -- | Remove trailing newlines/carriage returns. --- chomp :: String -> String --- chomp = reverse . dropWhile (`elem` "\r\n") . reverse +-- | Remove trailing newlines/carriage returns (and other whitespace). +textchomp :: Text -> Text +textchomp = T.stripEnd -- stripbrackets :: String -> String -- stripbrackets = dropWhile (`elem` "([") . reverse . dropWhile (`elem` "])") . reverse :: String -> String diff --git a/hledger-lib/hledger_journal.m4.md b/hledger-lib/hledger_journal.m4.md index 854aa4c3d..33a3fd130 100644 --- a/hledger-lib/hledger_journal.m4.md +++ b/hledger-lib/hledger_journal.m4.md @@ -1201,8 +1201,16 @@ can not accidentally alter their meaning, as in this example: With the `--forecast` flag, each periodic transaction rule generates future transactions recurring at the specified interval. These are not saved in the journal, but appear in all reports. -They will look like normal transactions, but with an extra -[tag](manual.html#tags-1) named `recur`, whose value is the generating period expression. +They will look like normal transactions, but with an extra [tag](manual.html#tags-1): + +- `generated-transaction:~ PERIODICEXPR` - shows that this was generated by a periodic transaction rule, and the period + +There is also a hidden tag, with an underscore prefix, which does not appear in hledger's output: + +- `_generated-transaction:~ PERIODICEXPR` + +This can be used to match transactions generated "just now", +rather than generated in the past and saved to the journal. Forecast transactions start on the first occurrence, and end on the last occurrence, of their interval within the forecast period. The forecast period: @@ -1251,11 +1259,11 @@ and ## Auto postings / transaction modifiers -Transaction modifier rules describe changes to be applied automatically to certain matched transactions. +Transaction modifier rules, AKA auto posting rules, describe changes to be applied automatically to certain matched transactions. Currently just one kind of change is possible - adding extra postings, which we call "automated postings" or just "auto postings". These rules become active when you use the `--auto` flag. -A transaction modifier, AKA auto posting rule, looks much like a normal transaction +A transaction modifier rule looks much like a normal transaction except the first line is an equals sign followed by a [query](manual.html#queries) that matches certain postings (mnemonic: `=` suggests matching). And each "posting" is actually a posting-generating rule: @@ -1309,6 +1317,12 @@ $ hledger print --auto assets:checking $20 ``` +### Auto postings and dates + +A [posting date](#posting-dates) (or secondary date) in the matched posting, +or (taking precedence) a posting date in the auto posting rule itself, +will also be used in the generated posting. + ### Auto postings and transaction balancing / inferred amounts / balance assertions Currently, transaction modifiers are applied / auto postings are added: @@ -1321,6 +1335,22 @@ after auto postings are added. This changed in hledger 1.12+; see [#893](https://github.com/simonmichael/hledger/issues/893) for background. +### Auto posting tags + +Postings added by transaction modifiers will have some extra [tags](#tags-1): + +- `generated-posting:= QUERY` - shows this was generated by an auto posting rule, and the query +- `_generated-posting:= QUERY` - a hidden tag, which does not appear in hledger's output. + This can be used to match postings generated "just now", + rather than generated in the past and saved to the journal. + +Also, any transaction that has been changed by transaction modifier rules will have these tags added: + +- `modified:` - this transaction was modified +- `_modified:` - a hidden tag not appearing in the comment; this transaction was modified "just now". + + + # EDITOR SUPPORT Helper modes exist for popular text editors, which make working with diff --git a/tests/forecast.test b/tests/forecast.test index c9b510480..bebd43f80 100644 --- a/tests/forecast.test +++ b/tests/forecast.test @@ -51,7 +51,7 @@ hledger print -b 2016-11 -e 2017-02 -f - --forecast assets:cash 2017/01/01 * marked cleared, and with a description - ; recur: monthly from 2016/1 + ; generated-transaction:~ monthly from 2016/1 income $-1000 expenses:food $20 expenses:leisure $15 @@ -118,7 +118,7 @@ Y 2000 >>> 2000/02/01 forecast - ; recur: 2/1 + ; generated-transaction:~ 2/1 >>>2 >>>=0 @@ -135,7 +135,7 @@ Y 2000 >>> 2000/01/15 forecast - ; recur: 15 + ; generated-transaction:~ 15 >>>2 >>>=0 @@ -152,7 +152,7 @@ Y 2000 >>> 2000/02/01 forecast - ; recur: next month + ; generated-transaction:~ next month >>>2 >>>=0 diff --git a/tests/journal/auto-postings.test b/tests/journal/auto-postings.test index be6211581..227a6dba8 100644 --- a/tests/journal/auto-postings.test +++ b/tests/journal/auto-postings.test @@ -15,11 +15,11 @@ # 1. print $ hledger print -f- --auto -2016/01/01 paycheck +2016/01/01 paycheck ; modified: income:remuneration $-100 - (liabilities:tax) $-33 ; income tax + (liabilities:tax) $-33 ; income tax, generated-posting:= ^income income:donations $-15 - (liabilities:tax) $-5 ; income tax + (liabilities:tax) $-5 ; income tax, generated-posting:= ^income assets:bank 2016/01/01 withdraw @@ -80,10 +80,10 @@ $ hledger register -f- --auto # 5. $ hledger print -f- --auto -2018/10/07 * MARKET +2018/10/07 * MARKET ; modified: expenses:groceries:food - [budget:groceries] $-20 - [assets:bank:checking] $20 + [budget:groceries] $-20 ; generated-posting:= ^expenses:groceries + [assets:bank:checking] $20 ; generated-posting:= ^expenses:groceries assets:bank:checking $-20 >= @@ -99,10 +99,10 @@ $ hledger print -f- --auto # 6. $ hledger -f- print --auto -x -2018/01/01 +2018/01/01 ; modified: (assets:billable:client1) 0.50h @ $90 - assets:receivable:client1 50.00h @ $90 - revenues:client1 $-4500 + assets:receivable:client1 50.00h @ $90 ; generated-posting:= assets:billable:client1 + revenues:client1 $-4500 ; generated-posting:= assets:billable:client1 >= @@ -117,10 +117,10 @@ $ hledger -f- print --auto -x # 7. $ hledger -f- print --auto -x -2018/01/01 +2018/01/01 ; modified: (assets:billable:client1) 0.50h - assets:receivable:client1 $50 - revenues:client1 $-50 + assets:receivable:client1 $50 ; generated-posting:= assets:billable:client1 + revenues:client1 $-50 ; generated-posting:= assets:billable:client1 >= @@ -135,10 +135,10 @@ $ hledger -f- print --auto -x # 8. $ hledger -f- print --auto -x -2018/01/01 +2018/01/01 ; modified: (assets:billable:client1) 0.50h @ $90 - assets:receivable:client1 0.50 "Client1 Hours" @ $100.00 - revenues:client1 $-50.00 + assets:receivable:client1 0.50 "Client1 Hours" @ $100.00 ; generated-posting:= assets:billable:client1 + revenues:client1 $-50.00 ; generated-posting:= assets:billable:client1 >= @@ -180,11 +180,11 @@ $ hledger print -f- --auto # 10. $ hledger -f- print --auto -2018/01/01 +2018/01/01 ; modified: Expenses:Joint:Widgets $100.00 @ £0.50 - Expenses:Joint $-100.00 @ £0.50 - Liabilities:Joint:Bob $50.00 @ £0.50 - Liabilities:Joint:Bill $50.00 @ £0.50 + Expenses:Joint $-100.00 @ £0.50 ; generated-posting:= ^Expenses:Joint + Liabilities:Joint:Bob $50.00 @ £0.50 ; generated-posting:= ^Expenses:Joint + Liabilities:Joint:Bill $50.00 @ £0.50 ; generated-posting:= ^Expenses:Joint Assets:Joint:Bank £-50.00 >=0 @@ -202,11 +202,11 @@ $ hledger -f- print --auto # 11. $ hledger -f- print --auto -2018/01/01 +2018/01/01 ; modified: Expenses:Joint:Widgets $100.00 @@ £50 - Expenses:Joint $-100.00 @@ £50 - Liabilities:Joint:Bob $50.00 @@ £25 - Liabilities:Joint:Bill $50.00 @@ £25 + Expenses:Joint $-100.00 @@ £50 ; generated-posting:= ^Expenses:Joint + Liabilities:Joint:Bob $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint + Liabilities:Joint:Bill $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint Assets:Joint:Bank £-50.00 >=0 @@ -231,11 +231,11 @@ $ hledger -f- print --auto # 12. $ hledger -f- print --auto -2018/01/01 +2018/01/01 ; modified: Expenses:Joint:Widgets $100.00 - Expenses:Joint $-100.00 @@ £50 - Liabilities:Joint:Bob $50.00 @@ £25 - Liabilities:Joint:Bill $50.00 @@ £25 + Expenses:Joint $-100.00 @@ £50 ; generated-posting:= ^Expenses:Joint + Liabilities:Joint:Bob $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint + Liabilities:Joint:Bill $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint Assets:Joint:Bank £-50.00 >=0 @@ -264,11 +264,11 @@ $ hledger print -f- --auto --forecast -b 2016-01 -e 2016-03 assets:bank 2016/02/01 paycheck - ; recur: monthly from 2016-01 + ; generated-transaction:~ monthly from 2016-01, modified: income:remuneration $-100 - (liabilities:tax) $-33 ; income tax + (liabilities:tax) $-33 ; income tax, generated-posting:= ^income income:donations $-15 - (liabilities:tax) $-5 ; income tax + (liabilities:tax) $-5 ; income tax, generated-posting:= ^income assets:bank >= @@ -280,7 +280,7 @@ $ hledger print -f- --forecast -b 2016-01 -e 2016-03 assets:bank 2016/02/01 paycheck - ; recur: monthly from 2016-01 + ; generated-transaction:~ monthly from 2016-01 income:remuneration $-100 income:donations $-15 assets:bank diff --git a/tests/journal/default-commodity.test b/tests/journal/default-commodity.test index 754f2bbee..c1ebec1ee 100644 --- a/tests/journal/default-commodity.test +++ b/tests/journal/default-commodity.test @@ -85,9 +85,9 @@ D $1000. (a) €1 >>> -2018/01/01 +2018/01/01 ; modified: (a) €1 - (b) €2 + (b) €2 ; generated-posting:= a >>>= diff --git a/tests/rewrite.test b/tests/rewrite.test index 5e60da0aa..50036da9e 100644 --- a/tests/rewrite.test +++ b/tests/rewrite.test @@ -1,4 +1,4 @@ -# Add proportional income tax (from documentation) +# 1. Add proportional income tax (from documentation) hledger rewrite -f- ^income --add-posting '(liabilities:tax) *.33 ; income tax' <<< 2016/1/1 paycheck @@ -10,11 +10,11 @@ hledger rewrite -f- ^income --add-posting '(liabilities:tax) *.33 ; income tax assets:cash $20 assets:bank >>> -2016/01/01 paycheck +2016/01/01 paycheck ; modified: income:remuneration $-100 - (liabilities:tax) $-33 ; income tax + (liabilities:tax) $-33 ; income tax, generated-posting:= ^income income:donations $-15 - (liabilities:tax) $-5 ; income tax + (liabilities:tax) $-5 ; income tax, generated-posting:= ^income assets:bank 2016/01/01 withdraw @@ -24,7 +24,8 @@ hledger rewrite -f- ^income --add-posting '(liabilities:tax) *.33 ; income tax >>>2 >>>=0 -# Duplicate posting for budgeting (from documentation) +# 2. Duplicate posting for budgeting (from documentation). +# It uses same date as the matched posting. hledger rewrite -f- expenses:gifts --add-posting '(budget:gifts) *-1' <<< 2016/1/1 withdraw @@ -39,15 +40,15 @@ hledger rewrite -f- expenses:gifts --add-posting '(budget:gifts) *-1' assets:cash $20 assets:bank -2016/01/01 gift +2016/01/01 gift ; modified: assets:cash $-15 expenses:gifts ; [1/2] - (budget:gifts) $-15 ; [2016/01/02] + (budget:gifts) $-15 ; [2016/01/02], generated-posting:= expenses:gifts >>>2 >>>=0 -# Add postings in another commodity +# 3. Add postings in another commodity hledger rewrite -f- <<< 2017/04/24 * 09:00-09:25 @@ -66,23 +67,23 @@ hledger rewrite -f- = ^assets:unbilled:client2 (assets:to bill:client2) *150.00 CAD >>> -2017/04/24 * 09:00-09:25 +2017/04/24 * 09:00-09:25 ; modified: (assets:unbilled:client1) 0.42h - (assets:to bill:client1) 42.00 CAD + (assets:to bill:client1) 42.00 CAD ; generated-posting:= ^assets:unbilled:client1 -2017/04/25 * 10:00-11:15 +2017/04/25 * 10:00-11:15 ; modified: (assets:unbilled:client1) 1.25h - (assets:to bill:client1) 125.00 CAD + (assets:to bill:client1) 125.00 CAD ; generated-posting:= ^assets:unbilled:client1 -2017/04/25 * 14:00-15:32 +2017/04/25 * 14:00-15:32 ; modified: (assets:unbilled:client2) 1.54h - (assets:to bill:client2) 231.00 CAD + (assets:to bill:client2) 231.00 CAD ; generated-posting:= ^assets:unbilled:client2 >>>2 >>>=0 -# Add postings with prices +# 4. Add postings with prices hledger rewrite -f- -B <<< 2017/04/24 * 09:00-09:25 @@ -103,25 +104,26 @@ hledger rewrite -f- -B assets:to bill:client2 *1.00 hours @ $150.00 income:consulting:client2 >>> -2017/04/24 * 09:00-09:25 +2017/04/24 * 09:00-09:25 ; modified: (assets:unbilled:client1) 0.42h - assets:to bill:client1 $42.00 - income:consulting:client1 + assets:to bill:client1 $42.00 ; generated-posting:= ^assets:unbilled:client1 + income:consulting:client1 ; generated-posting:= ^assets:unbilled:client1 -2017/04/25 * 10:00-11:15 +2017/04/25 * 10:00-11:15 ; modified: (assets:unbilled:client1) 1.25h - assets:to bill:client1 $125.00 - income:consulting:client1 + assets:to bill:client1 $125.00 ; generated-posting:= ^assets:unbilled:client1 + income:consulting:client1 ; generated-posting:= ^assets:unbilled:client1 -2017/04/25 * 14:00-15:32 +2017/04/25 * 14:00-15:32 ; modified: (assets:unbilled:client2) 1.54h - assets:to bill:client2 $231.00 - income:consulting:client2 + assets:to bill:client2 $231.00 ; generated-posting:= ^assets:unbilled:client2 + income:consulting:client2 ; generated-posting:= ^assets:unbilled:client2 >>>2 >>>=0 -# Add absolute bank processing fee +# 5. Add absolute bank processing fee +# XXX is "and" really processed here ? hledger rewrite -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee $5' --add-posting 'assets:bank $-5' <<< 2016/1/1 withdraw @@ -137,22 +139,22 @@ hledger rewrite -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee $5' - # income:remuneration $-100 # assets:bank >>> -2016/01/01 withdraw +2016/01/01 withdraw ; modified: assets:cash $20 assets:bank - expenses:fee $5 - assets:bank $-5 + expenses:fee $5 ; generated-posting:= assets:bank and amt:<0 + assets:bank $-5 ; generated-posting:= assets:bank and amt:<0 -2016/01/02 withdraw +2016/01/02 withdraw ; modified: assets:cash assets:bank $-30 - expenses:fee $5 - assets:bank $-5 + expenses:fee $5 ; generated-posting:= assets:bank and amt:<0 + assets:bank $-5 ; generated-posting:= assets:bank and amt:<0 >>>2 >>>=0 -# Rewrite rule within journal +# 6. Rewrite rule within journal hledger rewrite -f- date:2017/1 --add-posting 'Here comes Santa $0' <<< = ^assets:bank$ date:2017/1 amt:<0 @@ -186,32 +188,32 @@ hledger rewrite -f- date:2017/1 --add-posting 'Here comes Santa $0' = ^expenses not:housing not:grocery not:food (budget:misc) *-1 >>> -2016/12/31 +2016/12/31 ; modified: expenses:housing $600.00 - (budget:housing) $-600.00 + (budget:housing) $-600.00 ; generated-posting:= ^expenses:housing assets:cash -2017/01/01 +2017/01/01 ; modified: expenses:food $20.00 - (budget:food) $-20.00 - Here comes Santa 0 + (budget:food) $-20.00 ; generated-posting:= ^expenses:grocery ^expenses:food + Here comes Santa 0 ; generated-posting:= date:2017/1 expenses:leisure $15.00 - (budget:misc) $-15.00 - Here comes Santa 0 + (budget:misc) $-15.00 ; generated-posting:= ^expenses not:housing not:grocery not:food + Here comes Santa 0 ; generated-posting:= date:2017/1 expenses:grocery $30.00 - (budget:food) $-30.00 - Here comes Santa 0 + (budget:food) $-30.00 ; generated-posting:= ^expenses:grocery ^expenses:food + Here comes Santa 0 ; generated-posting:= date:2017/1 assets:cash - Here comes Santa 0 + Here comes Santa 0 ; generated-posting:= date:2017/1 -2017/01/02 +2017/01/02 ; modified: assets:cash $200.00 - Here comes Santa 0 + Here comes Santa 0 ; generated-posting:= date:2017/1 assets:bank - assets:bank $-1.60 - expenses:fee $1.60 ; cash withdraw fee - (budget:misc) $-1.60 - Here comes Santa 0 + assets:bank $-1.60 ; generated-posting:= ^assets:bank$ date:2017/1 amt:<0 + expenses:fee $1.60 ; cash withdraw fee, generated-posting:= ^assets:bank$ date:2017/1 amt:<0 + (budget:misc) $-1.60 ; generated-posting:= ^expenses not:housing not:grocery not:food + Here comes Santa 0 ; generated-posting:= date:2017/1 2017/02/01 assets:cash $100.00 @@ -220,7 +222,7 @@ hledger rewrite -f- date:2017/1 --add-posting 'Here comes Santa $0' >>>2 >>>=0 -# Rewrite using diff output +# 7. Rewrite using diff output hledger rewrite --diff -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee $5' --add-posting 'assets:bank $-5' <<< 2016/01/01 withdraw @@ -234,16 +236,18 @@ hledger rewrite --diff -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee --- - +++ - @@ -1,3 +1,5 @@ - 2016/01/01 withdraw +-2016/01/01 withdraw ++2016/01/01 withdraw ; modified: assets:cash $20 assets:bank -+ expenses:fee $5 -+ assets:bank $-5 ++ expenses:fee $5 ; generated-posting:= assets:bank and amt:<0 ++ assets:bank $-5 ; generated-posting:= assets:bank and amt:<0 @@ -5,3 +7,5 @@ - 2016/01/02 withdraw +-2016/01/02 withdraw ++2016/01/02 withdraw ; modified: assets:cash assets:bank $-30 -+ expenses:fee $5 -+ assets:bank $-5 ++ expenses:fee $5 ; generated-posting:= assets:bank and amt:<0 ++ assets:bank $-5 ; generated-posting:= assets:bank and amt:<0 >>>2 >>>=0