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.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
|
||||||
|
|||||||
@ -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:"
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
>>>=
|
>>>=
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user