register: with --depth, clip account names or aggregate postings rather than excluding them

This commit is contained in:
Simon Michael 2010-08-02 19:40:38 +00:00
parent a50d2fedd7
commit 506ec00818
4 changed files with 99 additions and 53 deletions

View File

@ -75,12 +75,14 @@ registerReport :: [Opt] -> FilterSpec -> Journal -> RegisterReport
registerReport opts fspec j = getitems ps nullposting startbal
where
ps | interval == NoInterval = displayableps
| otherwise = summarisePostings interval depth empty filterspan displayableps
(precedingps, displayableps, _) =
postingsMatchingDisplayExpr (displayExprFromOpts opts) $ journalPostings $ filterJournalPostings fspec j
| otherwise = summarisePostingsByInterval interval depth empty filterspan displayableps
(precedingps, displayableps, _) = postingsMatchingDisplayExpr (displayExprFromOpts opts)
$ depthClipPostings depth
$ journalPostings
$ filterJournalPostings fspec{depth=Nothing} j
startbal = sumPostings precedingps
(interval, depth, empty) = (intervalFromOpts opts, depthFromOpts opts, Empty `elem` opts)
filterspan = datespan fspec
(interval, depth, empty) = (intervalFromOpts opts, depthFromOpts opts, Empty `elem` opts)
-- | Generate register report line items.
getitems :: [Posting] -> Posting -> MixedAmount -> [RegisterReportItem]
@ -100,16 +102,6 @@ mkitem True p b = (ds, p, b)
where ds = case ptransaction p of Just (Transaction{tdate=da,tdescription=de}) -> Just (da,de)
Nothing -> Just (nulldate,"")
-- | Convert a list of postings into summary postings, one per interval.
summarisePostings :: Interval -> Maybe Int -> Bool -> DateSpan -> [Posting] -> [Posting]
summarisePostings interval depth empty filterspan ps = concatMap summarisespan $ splitSpan interval reportspan
where
summarisespan s = summarisePostingsInDateSpan s depth empty (postingsinspan s)
postingsinspan s = filter (isPostingInDateSpan s) ps
dataspan = postingsDateSpan ps
reportspan | empty = filterspan `orDatesFrom` dataspan
| otherwise = dataspan
-- | Date-sort and split a list of postings into three spans - postings matched
-- by the given display expression, and the preceding and following postings.
postingsMatchingDisplayExpr :: Maybe String -> [Posting] -> ([Posting],[Posting],[Posting])
@ -148,6 +140,19 @@ datedisplayexpr = do
compareop = choice $ map (try . string) ["<=",">=","==","<","=",">"]
-- XXX confusing, refactor
-- | Convert a list of postings into summary postings. Summary postings
-- are one per account per interval and aggregated to the specified depth
-- if any.
summarisePostingsByInterval :: Interval -> Maybe Int -> Bool -> DateSpan -> [Posting] -> [Posting]
summarisePostingsByInterval interval depth empty filterspan ps = concatMap summarisespan $ splitSpan interval reportspan
where
summarisespan s = summarisePostingsInDateSpan s depth empty (postingsinspan s)
postingsinspan s = filter (isPostingInDateSpan s) ps
dataspan = postingsDateSpan ps
reportspan | empty = filterspan `orDatesFrom` dataspan
| otherwise = dataspan
-- | Given a date span (representing a reporting interval) and a list of
-- postings within it: aggregate the postings so there is only one per
-- account, and adjust their date/description so that they will render
@ -159,8 +164,8 @@ datedisplayexpr = do
-- When a depth argument is present, postings to accounts of greater
-- depth are aggregated where possible.
--
-- The showempty flag forces the display of a zero-posting span
-- and also zero-posting accounts within the span.
-- The showempty flag includes spans with no postings and also postings
-- with 0 amount.
summarisePostingsInDateSpan :: DateSpan -> Maybe Int -> Bool -> [Posting] -> [Posting]
summarisePostingsInDateSpan (DateSpan b e) depth showempty ps
| null ps && (isNothing b || isNothing e) = []
@ -183,10 +188,20 @@ summarisePostingsInDateSpan (DateSpan b e) depth showempty ps
balancetoshowfor a =
(if isclipped a then inclbalof else exclbalof) (if null a then "top" else a)
-- | Clip the account names to the specified depth in a list of postings.
depthClipPostings :: Maybe Int -> [Posting] -> [Posting]
depthClipPostings depth = map (depthClipPosting depth)
-- | Clip a posting's account name to the specified depth.
depthClipPosting :: Maybe Int -> Posting -> Posting
depthClipPosting Nothing p = p
depthClipPosting (Just d) p@Posting{paccount=a} = p{paccount=clipAccountName d a}
tests_Register :: Test
tests_Register = TestList [
"summarisePostings" ~: do
summarisePostings Quarterly Nothing False (DateSpan Nothing Nothing) [] ~?= []
"summarisePostingsByInterval" ~: do
summarisePostingsByInterval Quarterly Nothing False (DateSpan Nothing Nothing) [] ~?= []
]

View File

@ -572,12 +572,17 @@ tests = TestList [
l <- samplejournal
let opts = [Depth "2"]
(registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` unlines
["2008/01/01 income income:salary $-1 $-1"
,"2008/06/01 gift income:gifts $-1 $-2"
,"2008/06/03 eat & shop expenses:food $1 $-1"
," expenses:supplies $1 0"
," assets:cash $-2 $-2"
,"2008/12/31 pay off liabilities:debts $1 $-1"
["2008/01/01 income assets:bank $1 $1"
," income:salary $-1 0"
,"2008/06/01 gift assets:bank $1 $1"
," income:gifts $-1 0"
,"2008/06/02 save assets:bank $1 $1"
," assets:bank $-1 0"
,"2008/06/03 eat & shop expenses:food $1 $1"
," expenses:supplies $1 $2"
," assets:cash $-2 0"
,"2008/12/31 pay off liabilities:debts $1 $1"
," assets:bank $-1 0"
]
,"show dollars" ~: show (dollars 1) ~?= "$1.00"

View File

@ -240,7 +240,7 @@ Here is the command-line help:
-C --cleared report only on cleared transactions
-U --uncleared report only on uncleared transactions
-B --cost, --basis report cost of commodities
--depth=N hide accounts/transactions deeper than this
--depth=N hide sub-accounts deeper than this
-d EXPR --display=EXPR show only transactions matching EXPR (where
EXPR is 'dOP[DATE]' and OP is <, <=, =, >=, >)
--effective use transactions' effective dates, if any
@ -284,17 +284,24 @@ Examples:
##### register
The register command displays postings, one per line, and their running
total. With a [reporting interval](#reporting-interval) it will aggregate
similar postings within each interval.
Examples:
The register command displays postings, one per line, and their running total.
With no [filter patterns](#filter-patterns), this is not all that different from [print](#print):
$ hledger register
$ hledger register --monthly -E rent
Note `--depth` doesn't work too well with `register` currently;
it hides deeper postings rather than aggregating them.
More typically, use it to see a specific account's activity:
$ hledger register assets:bank:checking
The `--depth` option limits the amount of sub-account detail displayed:
$ hledger register assets:bank:checking --depth 2
With a [reporting interval](#reporting-interval) it shows aggregated
summary postings within each interval:
$ hledger register --monthly rent
$ hledger register --monthly -E food --depth 4
##### balance
@ -651,8 +658,8 @@ subsequent dates may be written as month/day. Eg:
#### Period expressions
hledger supports flexible "period expressions" with the `-p/--period`
option to select transactions within a period of time (like 2009) and/or
with a reporting interval (like weekly). hledger period expressions are
option to select transactions within a period of time (eg in 2009) and/or
with a reporting interval (eg weekly). hledger period expressions are
similar but not identical to c++ ledger's.
Here is a basic period expression specifying the first quarter of 2009
@ -729,20 +736,8 @@ accurate running total. Eg, to show the balance since the first of the month:
#### Depth limiting
With the `--depth N` option, reports will show only the uppermost accounts
in the account tree, down to level N. This is most useful with
[balance](#balance) and [chart](#chart). For example:
$ hledger balance --depth 2
shows a more concise balance report displaying only the top two levels of
accounts.
It's currently not so useful with [register](#register), eg this:
$ hledger register --depth 1
shows only the postings in top-level accounts, which usually means
none.
in the account tree, down to level N. See the [balance](#balance),
[register](#register) and [chart](#chart) examples.
#### Prices

View File

@ -1,18 +1,49 @@
#
bin/hledger -f - register --depth 1
# this matches the second-level account but displays only the first-level name
bin/hledger -f - register aa --depth 1
<<<
2010/1/1 x
a:aa:aaa 1
b
>>>
2010/01/01 x a 1 1
>>>2
# this matches the second-level account, displays the second-level name, does not aggregate transactions
bin/hledger -f - register aa --depth 2
<<<
2010/1/1 x
a:aa 1
b:bb:bbb
2010/1/1 y
a:aa 1
b:bb:bbb
2010/1/2 z
a:aa 1
b:bb:bbb
>>>
2010/01/01 x a:aa 1 1
2010/01/01 y a:aa 1 2
2010/01/02 z a:aa 1 3
>>>2
#
bin/hledger -f - register --depth 1 --empty --monthly
# this matches the second-level account, displays the first-level name, aggregates by reporting interval
bin/hledger -f - register aa --depth 1 --daily
<<<
2010/1/1 x
a:aa 1
b:bb:bbb
2010/1/1 y
a:aa 1
b:bb:bbb
2010/1/2 z
a:aa 1
b:bb:bbb
>>>
2010/01/01 - 2010/01/01 a 2 2
2010/01/02 - 2010/01/02 a 1 3
>>>2