Merge pull request #914 from simonmichael/rule-tags

tags for matching rule-generated txns and postings
This commit is contained in:
Simon Michael 2019-07-17 18:38:14 +01:00 committed by GitHub
parent a5cae2a859
commit 35799142dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 211 additions and 114 deletions

View File

@ -21,7 +21,7 @@ import Text.Printf
import Hledger.Data.Types import Hledger.Data.Types
import Hledger.Data.Dates import Hledger.Data.Dates
import Hledger.Data.Amount import Hledger.Data.Amount
import Hledger.Data.Posting (post) import Hledger.Data.Posting (post, commentAddTagNextLine)
import Hledger.Data.Transaction import Hledger.Data.Transaction
import Hledger.Utils.UTF8IOCompat (error') import Hledger.Utils.UTF8IOCompat (error')
-- import Hledger.Utils.Debug -- import Hledger.Utils.Debug
@ -69,6 +69,10 @@ instance Show PeriodicTransaction where
-- | Generate transactions from 'PeriodicTransaction' within a 'DateSpan' -- | Generate transactions from 'PeriodicTransaction' within a 'DateSpan'
-- --
-- Note that new transactions require 'txnTieKnot' post-processing. -- 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" -- >>> _ptgen "monthly from 2017/1 to 2017/4"
-- 2017/01/01 -- 2017/01/01
@ -204,10 +208,14 @@ runPeriodicTransaction PeriodicTransaction{..} requestedspan =
tstatus = ptstatus tstatus = ptstatus
,tcode = ptcode ,tcode = ptcode
,tdescription = ptdescription ,tdescription = ptdescription
,tcomment = (if T.null ptcomment then "\n" else ptcomment) <> "recur: " <> ptperiodexpr ,tcomment = ptcomment
,ttags = ("recur", ptperiodexpr) : pttags `commentAddTagNextLine` ("generated-transaction",period)
,ttags = ("_generated-transaction",period) :
("generated-transaction" ,period) :
pttags
,tpostings = ptpostings ,tpostings = ptpostings
} }
period = "~ " <> ptperiodexpr
-- | Check that this date span begins at a boundary of this interval, -- | Check that this date span begins at a boundary of this interval,
-- or return an explanatory error message including the provided period expression -- or return an explanatory error message including the provided period expression

View File

@ -54,6 +54,10 @@ module Hledger.Data.Posting (
concatAccountNames, concatAccountNames,
accountNameApplyAliases, accountNameApplyAliases,
accountNameApplyAliasesMemo, accountNameApplyAliasesMemo,
-- * comment/tag operations
commentJoin,
commentAddTag,
commentAddTagNextLine,
-- * arithmetic -- * arithmetic
sumPostings, sumPostings,
-- * rendering -- * rendering
@ -356,6 +360,29 @@ postingValueAtDate prices styles mc d p = postingTransformAmount (mixedAmountVal
postingTransformAmount :: (MixedAmount -> MixedAmount) -> Posting -> Posting postingTransformAmount :: (MixedAmount -> MixedAmount) -> Posting -> Posting
postingTransformAmount f p@Posting{pamount=a} = p{pamount=f a} 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 -- tests
@ -387,5 +414,14 @@ tests_Posting = tests "Posting" [
,concatAccountNames ["a","(b)","[c:d]"] `is` "(a:b:c:d)" ,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:"
]
] ]

View File

@ -12,6 +12,7 @@ module Hledger.Data.TransactionModifier (
) )
where where
import Control.Applicative ((<|>))
import Data.Maybe import Data.Maybe
#if !(MIN_VERSION_base(4,11,0)) #if !(MIN_VERSION_base(4,11,0))
import Data.Monoid ((<>)) import Data.Monoid ((<>))
@ -23,6 +24,7 @@ import Hledger.Data.Dates
import Hledger.Data.Amount import Hledger.Data.Amount
import Hledger.Data.Transaction import Hledger.Data.Transaction
import Hledger.Query import Hledger.Query
import Hledger.Data.Posting (commentJoin, commentAddTag)
import Hledger.Utils.UTF8IOCompat (error') import Hledger.Utils.UTF8IOCompat (error')
import Hledger.Utils.Debug import Hledger.Utils.Debug
@ -36,7 +38,15 @@ import Hledger.Utils.Debug
modifyTransactions :: [TransactionModifier] -> [Transaction] -> [Transaction] modifyTransactions :: [TransactionModifier] -> [Transaction] -> [Transaction]
modifyTransactions tmods = map applymods modifyTransactions tmods = map applymods
where 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, -- | Converts a 'TransactionModifier' to a 'Transaction'-transforming function,
-- which applies the modification(s) specified by the TransactionModifier. -- which applies the modification(s) specified by the TransactionModifier.
@ -61,10 +71,10 @@ modifyTransactions tmods = map applymods
-- --
transactionModifierToFunction :: TransactionModifier -> (Transaction -> Transaction) transactionModifierToFunction :: TransactionModifier -> (Transaction -> Transaction)
transactionModifierToFunction mt = 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 where
q = simplifyQuery $ tmParseQuery mt (error' "a transaction modifier's query cannot depend on current date") 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 generatePostings ps = [p' | p <- ps
, p' <- if q `matchesPosting` p then p:[ m p | m <- mods] else [p]] , 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"). -- 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. -- 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. -- If the old posting had a total-priced amount, the new posting's multiplied amount will be unit-priced.
tmPostingRuleToFunction :: TMPostingRule -> (Posting -> Posting) -- The new posting will have two tags added: a normal generated-posting: tag which also appears in the comment,
tmPostingRuleToFunction pr = -- 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 \p -> renderPostingCommentDates $ pr
{ pdate = pdate p { pdate = pdate pr <|> pdate p
, pdate2 = pdate2 p , pdate2 = pdate2 pr <|> pdate2 p
, pamount = amount' p , pamount = amount' p
, pcomment = pcomment pr `commentAddTag` ("generated-posting",qry)
, ptags = ("generated-posting", qry) :
("_generated-posting",qry) :
ptags pr
} }
where where
qry = "= " <> querytxt
amount' = case postingRuleMultiplier pr of amount' = case postingRuleMultiplier pr of
Nothing -> const $ pamount pr Nothing -> const $ pamount pr
Just n -> \p -> Just n -> \p ->
@ -123,7 +142,7 @@ postingRuleMultiplier p =
renderPostingCommentDates :: Posting -> Posting renderPostingCommentDates :: Posting -> Posting
renderPostingCommentDates p = p { pcomment = comment' } renderPostingCommentDates p = p { pcomment = comment' }
where 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' comment'
| T.null datesComment = pcomment p | T.null dates = pcomment p
| otherwise = T.intercalate "\n" $ filter (not . T.null) [T.strip $ pcomment p, "[" <> datesComment <> "]"] | otherwise = ("[" <> dates <> "]") `commentJoin` pcomment p

View File

@ -30,7 +30,7 @@ module Hledger.Utils.Text
textstrip, textstrip,
textlstrip, textlstrip,
textrstrip, textrstrip,
-- chomp, textchomp,
-- elideLeft, -- elideLeft,
textElideRight, textElideRight,
-- formatString, -- formatString,
@ -90,9 +90,9 @@ textlstrip = T.dropWhile (`elem` (" \t" :: String)) :: Text -> Text -- XXX isSpa
textrstrip = T.reverse . textlstrip . T.reverse textrstrip = T.reverse . textlstrip . T.reverse
textrstrip :: Text -> Text textrstrip :: Text -> Text
-- -- | Remove trailing newlines/carriage returns. -- | Remove trailing newlines/carriage returns (and other whitespace).
-- chomp :: String -> String textchomp :: Text -> Text
-- chomp = reverse . dropWhile (`elem` "\r\n") . reverse textchomp = T.stripEnd
-- stripbrackets :: String -> String -- stripbrackets :: String -> String
-- stripbrackets = dropWhile (`elem` "([") . reverse . dropWhile (`elem` "])") . reverse :: String -> String -- stripbrackets = dropWhile (`elem` "([") . reverse . dropWhile (`elem` "])") . reverse :: String -> String

View File

@ -1201,8 +1201,16 @@ can not accidentally alter their meaning, as in this example:
With the `--forecast` flag, each periodic transaction rule generates With the `--forecast` flag, each periodic transaction rule generates
future transactions recurring at the specified interval. future transactions recurring at the specified interval.
These are not saved in the journal, but appear in all reports. These are not saved in the journal, but appear in all reports.
They will look like normal transactions, but with an extra They will look like normal transactions, but with an extra [tag](manual.html#tags-1):
[tag](manual.html#tags-1) named `recur`, whose value is the generating period expression.
- `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, Forecast transactions start on the first occurrence, and end on the last occurrence,
of their interval within the forecast period. The forecast period: of their interval within the forecast period. The forecast period:
@ -1251,11 +1259,11 @@ and
## Auto postings / transaction modifiers ## 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". 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. 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 except the first line is an equals sign followed by a [query](manual.html#queries) that matches certain postings
(mnemonic: `=` suggests matching). (mnemonic: `=` suggests matching).
And each "posting" is actually a posting-generating rule: And each "posting" is actually a posting-generating rule:
@ -1309,6 +1317,12 @@ $ hledger print --auto
assets:checking $20 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 ### Auto postings and transaction balancing / inferred amounts / balance assertions
Currently, transaction modifiers are applied / auto postings are added: 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 [#893](https://github.com/simonmichael/hledger/issues/893) for
background. 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 # EDITOR SUPPORT
Helper modes exist for popular text editors, which make working with Helper modes exist for popular text editors, which make working with

View File

@ -51,7 +51,7 @@ hledger print -b 2016-11 -e 2017-02 -f - --forecast
assets:cash assets:cash
2017/01/01 * marked cleared, and with a description 2017/01/01 * marked cleared, and with a description
; recur: monthly from 2016/1 ; generated-transaction:~ monthly from 2016/1
income $-1000 income $-1000
expenses:food $20 expenses:food $20
expenses:leisure $15 expenses:leisure $15
@ -118,7 +118,7 @@ Y 2000
>>> >>>
2000/02/01 forecast 2000/02/01 forecast
; recur: 2/1 ; generated-transaction:~ 2/1
>>>2 >>>2
>>>=0 >>>=0
@ -135,7 +135,7 @@ Y 2000
>>> >>>
2000/01/15 forecast 2000/01/15 forecast
; recur: 15 ; generated-transaction:~ 15
>>>2 >>>2
>>>=0 >>>=0
@ -152,7 +152,7 @@ Y 2000
>>> >>>
2000/02/01 forecast 2000/02/01 forecast
; recur: next month ; generated-transaction:~ next month
>>>2 >>>2
>>>=0 >>>=0

View File

@ -15,11 +15,11 @@
# 1. print # 1. print
$ hledger print -f- --auto $ hledger print -f- --auto
2016/01/01 paycheck 2016/01/01 paycheck ; modified:
income:remuneration $-100 income:remuneration $-100
(liabilities:tax) $-33 ; income tax (liabilities:tax) $-33 ; income tax, generated-posting:= ^income
income:donations $-15 income:donations $-15
(liabilities:tax) $-5 ; income tax (liabilities:tax) $-5 ; income tax, generated-posting:= ^income
assets:bank assets:bank
2016/01/01 withdraw 2016/01/01 withdraw
@ -80,10 +80,10 @@ $ hledger register -f- --auto
# 5. # 5.
$ hledger print -f- --auto $ hledger print -f- --auto
2018/10/07 * MARKET 2018/10/07 * MARKET ; modified:
expenses:groceries:food expenses:groceries:food
[budget:groceries] $-20 [budget:groceries] $-20 ; generated-posting:= ^expenses:groceries
[assets:bank:checking] $20 [assets:bank:checking] $20 ; generated-posting:= ^expenses:groceries
assets:bank:checking $-20 assets:bank:checking $-20
>= >=
@ -99,10 +99,10 @@ $ hledger print -f- --auto
# 6. # 6.
$ hledger -f- print --auto -x $ hledger -f- print --auto -x
2018/01/01 2018/01/01 ; modified:
(assets:billable:client1) 0.50h @ $90 (assets:billable:client1) 0.50h @ $90
assets:receivable:client1 50.00h @ $90 assets:receivable:client1 50.00h @ $90 ; generated-posting:= assets:billable:client1
revenues:client1 $-4500 revenues:client1 $-4500 ; generated-posting:= assets:billable:client1
>= >=
@ -117,10 +117,10 @@ $ hledger -f- print --auto -x
# 7. # 7.
$ hledger -f- print --auto -x $ hledger -f- print --auto -x
2018/01/01 2018/01/01 ; modified:
(assets:billable:client1) 0.50h (assets:billable:client1) 0.50h
assets:receivable:client1 $50 assets:receivable:client1 $50 ; generated-posting:= assets:billable:client1
revenues:client1 $-50 revenues:client1 $-50 ; generated-posting:= assets:billable:client1
>= >=
@ -135,10 +135,10 @@ $ hledger -f- print --auto -x
# 8. # 8.
$ hledger -f- print --auto -x $ hledger -f- print --auto -x
2018/01/01 2018/01/01 ; modified:
(assets:billable:client1) 0.50h @ $90 (assets:billable:client1) 0.50h @ $90
assets:receivable:client1 0.50 "Client1 Hours" @ $100.00 assets:receivable:client1 0.50 "Client1 Hours" @ $100.00 ; generated-posting:= assets:billable:client1
revenues:client1 $-50.00 revenues:client1 $-50.00 ; generated-posting:= assets:billable:client1
>= >=
@ -180,11 +180,11 @@ $ hledger print -f- --auto
# 10. # 10.
$ hledger -f- print --auto $ hledger -f- print --auto
2018/01/01 2018/01/01 ; modified:
Expenses:Joint:Widgets $100.00 @ £0.50 Expenses:Joint:Widgets $100.00 @ £0.50
Expenses:Joint $-100.00 @ £0.50 Expenses:Joint $-100.00 @ £0.50 ; generated-posting:= ^Expenses:Joint
Liabilities:Joint:Bob $50.00 @ £0.50 Liabilities:Joint:Bob $50.00 @ £0.50 ; generated-posting:= ^Expenses:Joint
Liabilities:Joint:Bill $50.00 @ £0.50 Liabilities:Joint:Bill $50.00 @ £0.50 ; generated-posting:= ^Expenses:Joint
Assets:Joint:Bank £-50.00 Assets:Joint:Bank £-50.00
>=0 >=0
@ -202,11 +202,11 @@ $ hledger -f- print --auto
# 11. # 11.
$ hledger -f- print --auto $ hledger -f- print --auto
2018/01/01 2018/01/01 ; modified:
Expenses:Joint:Widgets $100.00 @@ £50 Expenses:Joint:Widgets $100.00 @@ £50
Expenses:Joint $-100.00 @@ £50 Expenses:Joint $-100.00 @@ £50 ; generated-posting:= ^Expenses:Joint
Liabilities:Joint:Bob $50.00 @@ £25 Liabilities:Joint:Bob $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint
Liabilities:Joint:Bill $50.00 @@ £25 Liabilities:Joint:Bill $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint
Assets:Joint:Bank £-50.00 Assets:Joint:Bank £-50.00
>=0 >=0
@ -231,11 +231,11 @@ $ hledger -f- print --auto
# 12. # 12.
$ hledger -f- print --auto $ hledger -f- print --auto
2018/01/01 2018/01/01 ; modified:
Expenses:Joint:Widgets $100.00 Expenses:Joint:Widgets $100.00
Expenses:Joint $-100.00 @@ £50 Expenses:Joint $-100.00 @@ £50 ; generated-posting:= ^Expenses:Joint
Liabilities:Joint:Bob $50.00 @@ £25 Liabilities:Joint:Bob $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint
Liabilities:Joint:Bill $50.00 @@ £25 Liabilities:Joint:Bill $50.00 @@ £25 ; generated-posting:= ^Expenses:Joint
Assets:Joint:Bank £-50.00 Assets:Joint:Bank £-50.00
>=0 >=0
@ -264,11 +264,11 @@ $ hledger print -f- --auto --forecast -b 2016-01 -e 2016-03
assets:bank assets:bank
2016/02/01 paycheck 2016/02/01 paycheck
; recur: monthly from 2016-01 ; generated-transaction:~ monthly from 2016-01, modified:
income:remuneration $-100 income:remuneration $-100
(liabilities:tax) $-33 ; income tax (liabilities:tax) $-33 ; income tax, generated-posting:= ^income
income:donations $-15 income:donations $-15
(liabilities:tax) $-5 ; income tax (liabilities:tax) $-5 ; income tax, generated-posting:= ^income
assets:bank assets:bank
>= >=
@ -280,7 +280,7 @@ $ hledger print -f- --forecast -b 2016-01 -e 2016-03
assets:bank assets:bank
2016/02/01 paycheck 2016/02/01 paycheck
; recur: monthly from 2016-01 ; generated-transaction:~ monthly from 2016-01
income:remuneration $-100 income:remuneration $-100
income:donations $-15 income:donations $-15
assets:bank assets:bank

View File

@ -85,9 +85,9 @@ D $1000.
(a) €1 (a) €1
>>> >>>
2018/01/01 2018/01/01 ; modified:
(a) €1 (a) €1
(b) €2 (b) €2 ; generated-posting:= a
>>>= >>>=

View File

@ -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' hledger rewrite -f- ^income --add-posting '(liabilities:tax) *.33 ; income tax'
<<< <<<
2016/1/1 paycheck 2016/1/1 paycheck
@ -10,11 +10,11 @@ hledger rewrite -f- ^income --add-posting '(liabilities:tax) *.33 ; income tax
assets:cash $20 assets:cash $20
assets:bank assets:bank
>>> >>>
2016/01/01 paycheck 2016/01/01 paycheck ; modified:
income:remuneration $-100 income:remuneration $-100
(liabilities:tax) $-33 ; income tax (liabilities:tax) $-33 ; income tax, generated-posting:= ^income
income:donations $-15 income:donations $-15
(liabilities:tax) $-5 ; income tax (liabilities:tax) $-5 ; income tax, generated-posting:= ^income
assets:bank assets:bank
2016/01/01 withdraw 2016/01/01 withdraw
@ -24,7 +24,8 @@ hledger rewrite -f- ^income --add-posting '(liabilities:tax) *.33 ; income tax
>>>2 >>>2
>>>=0 >>>=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' hledger rewrite -f- expenses:gifts --add-posting '(budget:gifts) *-1'
<<< <<<
2016/1/1 withdraw 2016/1/1 withdraw
@ -39,15 +40,15 @@ hledger rewrite -f- expenses:gifts --add-posting '(budget:gifts) *-1'
assets:cash $20 assets:cash $20
assets:bank assets:bank
2016/01/01 gift 2016/01/01 gift ; modified:
assets:cash $-15 assets:cash $-15
expenses:gifts ; [1/2] expenses:gifts ; [1/2]
(budget:gifts) $-15 ; [2016/01/02] (budget:gifts) $-15 ; [2016/01/02], generated-posting:= expenses:gifts
>>>2 >>>2
>>>=0 >>>=0
# Add postings in another commodity # 3. Add postings in another commodity
hledger rewrite -f- hledger rewrite -f-
<<< <<<
2017/04/24 * 09:00-09:25 2017/04/24 * 09:00-09:25
@ -66,23 +67,23 @@ hledger rewrite -f-
= ^assets:unbilled:client2 = ^assets:unbilled:client2
(assets:to bill:client2) *150.00 CAD (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: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: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:unbilled:client2) 1.54h
(assets:to bill:client2) 231.00 CAD (assets:to bill:client2) 231.00 CAD ; generated-posting:= ^assets:unbilled:client2
>>>2 >>>2
>>>=0 >>>=0
# Add postings with prices # 4. Add postings with prices
hledger rewrite -f- -B hledger rewrite -f- -B
<<< <<<
2017/04/24 * 09:00-09:25 2017/04/24 * 09:00-09:25
@ -103,25 +104,26 @@ hledger rewrite -f- -B
assets:to bill:client2 *1.00 hours @ $150.00 assets:to bill:client2 *1.00 hours @ $150.00
income:consulting:client2 income:consulting:client2
>>> >>>
2017/04/24 * 09:00-09:25 2017/04/24 * 09:00-09:25 ; modified:
(assets:unbilled:client1) 0.42h (assets:unbilled:client1) 0.42h
assets:to bill:client1 $42.00 assets:to bill:client1 $42.00 ; generated-posting:= ^assets:unbilled:client1
income:consulting: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:unbilled:client1) 1.25h
assets:to bill:client1 $125.00 assets:to bill:client1 $125.00 ; generated-posting:= ^assets:unbilled:client1
income:consulting: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:unbilled:client2) 1.54h
assets:to bill:client2 $231.00 assets:to bill:client2 $231.00 ; generated-posting:= ^assets:unbilled:client2
income:consulting:client2 income:consulting:client2 ; generated-posting:= ^assets:unbilled:client2
>>>2 >>>2
>>>=0 >>>=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' hledger rewrite -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee $5' --add-posting 'assets:bank $-5'
<<< <<<
2016/1/1 withdraw 2016/1/1 withdraw
@ -137,22 +139,22 @@ hledger rewrite -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee $5' -
# income:remuneration $-100 # income:remuneration $-100
# assets:bank # assets:bank
>>> >>>
2016/01/01 withdraw 2016/01/01 withdraw ; modified:
assets:cash $20 assets:cash $20
assets:bank assets:bank
expenses:fee $5 expenses:fee $5 ; generated-posting:= assets:bank and amt:<0
assets:bank $-5 assets:bank $-5 ; generated-posting:= assets:bank and amt:<0
2016/01/02 withdraw 2016/01/02 withdraw ; modified:
assets:cash assets:cash
assets:bank $-30 assets:bank $-30
expenses:fee $5 expenses:fee $5 ; generated-posting:= assets:bank and amt:<0
assets:bank $-5 assets:bank $-5 ; generated-posting:= assets:bank and amt:<0
>>>2 >>>2
>>>=0 >>>=0
# Rewrite rule within journal # 6. Rewrite rule within journal
hledger rewrite -f- date:2017/1 --add-posting 'Here comes Santa $0' hledger rewrite -f- date:2017/1 --add-posting 'Here comes Santa $0'
<<< <<<
= ^assets:bank$ date:2017/1 amt:<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 = ^expenses not:housing not:grocery not:food
(budget:misc) *-1 (budget:misc) *-1
>>> >>>
2016/12/31 2016/12/31 ; modified:
expenses:housing $600.00 expenses:housing $600.00
(budget:housing) $-600.00 (budget:housing) $-600.00 ; generated-posting:= ^expenses:housing
assets:cash assets:cash
2017/01/01 2017/01/01 ; modified:
expenses:food $20.00 expenses:food $20.00
(budget:food) $-20.00 (budget:food) $-20.00 ; generated-posting:= ^expenses:grocery ^expenses:food
Here comes Santa 0 Here comes Santa 0 ; generated-posting:= date:2017/1
expenses:leisure $15.00 expenses:leisure $15.00
(budget:misc) $-15.00 (budget:misc) $-15.00 ; generated-posting:= ^expenses not:housing not:grocery not:food
Here comes Santa 0 Here comes Santa 0 ; generated-posting:= date:2017/1
expenses:grocery $30.00 expenses:grocery $30.00
(budget:food) $-30.00 (budget:food) $-30.00 ; generated-posting:= ^expenses:grocery ^expenses:food
Here comes Santa 0 Here comes Santa 0 ; generated-posting:= date:2017/1
assets:cash 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 assets:cash $200.00
Here comes Santa 0 Here comes Santa 0 ; generated-posting:= date:2017/1
assets:bank assets:bank
assets:bank $-1.60 assets:bank $-1.60 ; generated-posting:= ^assets:bank$ date:2017/1 amt:<0
expenses:fee $1.60 ; cash withdraw fee expenses:fee $1.60 ; cash withdraw fee, generated-posting:= ^assets:bank$ date:2017/1 amt:<0
(budget:misc) $-1.60 (budget:misc) $-1.60 ; generated-posting:= ^expenses not:housing not:grocery not:food
Here comes Santa 0 Here comes Santa 0 ; generated-posting:= date:2017/1
2017/02/01 2017/02/01
assets:cash $100.00 assets:cash $100.00
@ -220,7 +222,7 @@ hledger rewrite -f- date:2017/1 --add-posting 'Here comes Santa $0'
>>>2 >>>2
>>>=0 >>>=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' hledger rewrite --diff -f- assets:bank and 'amt:<0' --add-posting 'expenses:fee $5' --add-posting 'assets:bank $-5'
<<< <<<
2016/01/01 withdraw 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 @@ @@ -1,3 +1,5 @@
2016/01/01 withdraw -2016/01/01 withdraw
+2016/01/01 withdraw ; modified:
assets:cash $20 assets:cash $20
assets:bank assets:bank
+ expenses:fee $5 + expenses:fee $5 ; generated-posting:= assets:bank and amt:<0
+ assets:bank $-5 + assets:bank $-5 ; generated-posting:= assets:bank and amt:<0
@@ -5,3 +7,5 @@ @@ -5,3 +7,5 @@
2016/01/02 withdraw -2016/01/02 withdraw
+2016/01/02 withdraw ; modified:
assets:cash assets:cash
assets:bank $-30 assets:bank $-30
+ expenses:fee $5 + expenses:fee $5 ; generated-posting:= assets:bank and amt:<0
+ assets:bank $-5 + assets:bank $-5 ; generated-posting:= assets:bank and amt:<0
>>>2 >>>2
>>>=0 >>>=0