From c22e4e85d0aef183f00ce3b0c61b8dd5d52662ad Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Fri, 23 Sep 2011 00:09:39 +0000 Subject: [PATCH] register: be better at showing empty intervals with --empty and a query pattern --- hledger-lib/Hledger/Data/Dates.hs | 14 +++++++ hledger-lib/Hledger/Reports.hs | 30 ++++++++----- tests/register-intervals.test | 70 +++++++++++++++++++++++++++++++ tests/reporting-intervals.test | 50 ---------------------- 4 files changed, 103 insertions(+), 61 deletions(-) create mode 100644 tests/register-intervals.test delete mode 100644 tests/reporting-intervals.test diff --git a/hledger-lib/Hledger/Data/Dates.hs b/hledger-lib/Hledger/Data/Dates.hs index 5f3bd952e..fa0de846e 100644 --- a/hledger-lib/Hledger/Data/Dates.hs +++ b/hledger-lib/Hledger/Data/Dates.hs @@ -116,6 +116,20 @@ orDatesFrom (DateSpan a1 b1) (DateSpan a2 b2) = DateSpan a b where a = if isJust a1 then a1 else a2 b = if isJust b1 then b1 else b2 +-- | Calculate the intersection of two datespans. +spanIntersect (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan b e + where + b = latest b1 b2 + e = earliest e1 e2 + +latest d Nothing = d +latest Nothing d = d +latest (Just d1) (Just d2) = Just $ max d1 d2 + +earliest d Nothing = d +earliest Nothing d = d +earliest (Just d1) (Just d2) = Just $ min d1 d2 + -- | Parse a period expression to an Interval and overall DateSpan using -- the provided reference date, or return a parse error. parsePeriodExpr :: Day -> String -> Either ParseError (Interval, DateSpan) diff --git a/hledger-lib/Hledger/Reports.hs b/hledger-lib/Hledger/Reports.hs index 8ee7e891a..854730236 100644 --- a/hledger-lib/Hledger/Reports.hs +++ b/hledger-lib/Hledger/Reports.hs @@ -224,17 +224,28 @@ postingsReport :: ReportOpts -> FilterSpec -> Journal -> PostingsReport postingsReport opts fspec j = (totallabel, postingsReportItems ps nullposting startbal (+)) where ps | interval == NoInterval = displayableps - | otherwise = summarisePostingsByInterval interval depth empty filterspan displayableps - (precedingps, displayableps, _) = postingsMatchingDisplayExpr (display_ opts) + | otherwise = summarisePostingsByInterval interval depth empty reportspan displayableps + j' = journalSelectingDateFromOpts opts + $ journalSelectingAmountFromOpts opts + j + (precedingps, displayableps, _) = postingsMatchingDisplayExpr (display_ opts) $ depthClipPostings depth $ journalPostings $ filterJournalPostings fspec{depth=Nothing} - $ journalSelectingDateFromOpts opts - $ journalSelectingAmountFromOpts opts - j + j' + (interval, depth, empty, displayexpr) = (intervalFromOpts opts, depth_ opts, empty_ opts, display_ opts) + journalspan = journalDateSpan j' + -- requestedspan should be the intersection of any span specified + -- with period options and any span specified with display option. + -- The latter is not easily available, fake it for now. + requestedspan = periodspan `spanIntersect` displayspan + periodspan = datespan fspec + displayspan = postingsDateSpan ps + where (_,ps,_) = postingsMatchingDisplayExpr displayexpr $ journalPostings j' + matchedspan = postingsDateSpan displayableps + reportspan | empty = requestedspan `orDatesFrom` journalspan + | otherwise = requestedspan `spanIntersect` matchedspan startbal = sumPostings precedingps - filterspan = datespan fspec - (interval, depth, empty) = (intervalFromOpts opts, depth_ opts, empty_ opts) totallabel = "Total" balancelabel = "Balance" @@ -309,13 +320,10 @@ depthClipPosting (Just d) p@Posting{paccount=a} = p{paccount=clipAccountName d a -- 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 +summarisePostingsByInterval interval depth empty reportspan 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 diff --git a/tests/register-intervals.test b/tests/register-intervals.test new file mode 100644 index 000000000..07869dd78 --- /dev/null +++ b/tests/register-intervals.test @@ -0,0 +1,70 @@ +# 1. monthly reporting interval, no end dates, shows just the intervals with data: +bin/hledger -f- register --period 'monthly' +<<< +2011/2/1 + (a) 1 +>>> +2011/02/01 - 2011/02/28 a 1 1 +>>>=0 + +# 2. or with a query pattern, just the intervals with matched data: +bin/hledger -f- register --period 'monthly' b +<<< +2011/1/1 + (a) 1 + +2011/2/1 + (b) 1 +>>> +2011/02/01 - 2011/02/28 b 1 1 +>>>=0 + +# 3. with --empty, show all intervals spanned by the journal +# (unlike current ledger, but more useful) +bin/hledger -f- register --period 'monthly' b --empty +<<< +2011/1/1 + (a) 1 + +2011/2/1 + (b) 1 + +2011/3/1 + (c) 1 +>>> +2011/01/01 - 2011/01/31 0 0 +2011/02/01 - 2011/02/28 b 1 1 +2011/03/01 - 2011/03/31 0 1 +>>>=0 + +# 4. any specified begin/end dates limit the intervals reported +bin/hledger -f- register --period 'monthly to 2011/3/1' b --empty +<<< +2011/1/1 + (a) 1 + +2011/2/1 + (b) 1 + +2011/3/1 + (c) 1 +>>> +2011/01/01 - 2011/01/31 0 0 +2011/02/01 - 2011/02/28 b 1 1 +>>>=0 + +# 5. likewise for date-restricting display expressions +bin/hledger -f- register --period 'monthly to 2011/2/1' b --empty --display 'd<[2011/2/1]' +<<< +2011/1/1 + (a) 1 + +2011/2/1 + (b) 1 + +2011/3/1 + (c) 1 +>>> +2011/01/01 - 2011/01/31 0 0 +>>>=0 + diff --git a/tests/reporting-intervals.test b/tests/reporting-intervals.test deleted file mode 100644 index 015958d24..000000000 --- a/tests/reporting-intervals.test +++ /dev/null @@ -1,50 +0,0 @@ -# -# monthly reporting interval, no end dates, shows just the intervals with data: -bin/hledger -f- register --period 'monthly' -<<< -2010/2/1 x - a 1 - b ->>> -2010/02/01 - 2010/02/28 a 1 1 - b -1 0 ->>>=0 - -# -# with --empty, the same: -bin/hledger -f- register --period 'monthly' --empty -<<< -2010/2/1 x - a 1 - b ->>> -2010/02/01 - 2010/02/28 a 1 1 - b -1 0 ->>>=0 - -# -# with --empty and start/end dates, show all intervals covering the specified period -bin/hledger -f- register --period 'monthly from 2010/1/10 to 2010/3/15' --empty -<<< -2010/2/1 x - a 1 - b ->>> -2010/01/01 - 2010/01/31 0 0 -2010/02/01 - 2010/02/28 a 1 1 - b -1 0 -2010/03/01 - 2010/03/31 0 0 ->>>=0 - -# -# with just one start/end date, get the other from the data -bin/hledger -f- register --period 'monthly from 2010/1/10' --empty -<<< -2010/2/1 x - a 1 - b ->>> -2010/01/01 - 2010/01/31 0 0 -2010/02/01 - 2010/02/28 a 1 1 - b -1 0 ->>>=0