Merge pull request #914 from simonmichael/rule-tags
tags for matching rule-generated txns and postings
This commit is contained in:
		
							parent
							
								
									a5cae2a859
								
							
						
					
					
						commit
						35799142dd
					
				| @ -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 | ||||
|  | ||||
| @ -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:" | ||||
|   ] | ||||
|  ] | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -85,9 +85,9 @@ D $1000. | ||||
|   (a)  €1 | ||||
| 
 | ||||
| >>> | ||||
| 2018/01/01 | ||||
| 2018/01/01  ; modified: | ||||
|     (a)              €1 | ||||
|     (b)              €2 | ||||
|     (b)              €2  ; generated-posting:= a | ||||
| 
 | ||||
| >>>= | ||||
| 
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user