reg: fix sorting regression with --date2 (#326)
And rewrite/clarify postingsReport.
This commit is contained in:
parent
6cbc0ceb0d
commit
884c0b8a58
@ -53,51 +53,83 @@ type PostingsReportItem = (Maybe Day -- The posting date, if this is the firs
|
|||||||
postingsReport :: ReportOpts -> Query -> Journal -> PostingsReport
|
postingsReport :: ReportOpts -> Query -> Journal -> PostingsReport
|
||||||
postingsReport opts q j = (totallabel, items)
|
postingsReport opts q j = (totallabel, items)
|
||||||
where
|
where
|
||||||
-- figure out adjusted queries & spans like multiBalanceReport
|
-- XXX combined date:/date2:/--date2 is not robust, you can confuse it
|
||||||
symq = dbg1 "symq" $ filterQuery queryIsSym $ dbg1 "requested q" q
|
-- cf tests/register/date2.test
|
||||||
depth = queryDepth q
|
|
||||||
depthless = filterQuery (not . queryIsDepth)
|
|
||||||
datelessq = filterQuery (not . queryIsDateOrDate2) q
|
|
||||||
-- XXX date:/date2:/--date2 handling is not robust, combinations of these can confuse it
|
|
||||||
dateq = filterQuery queryIsDateOrDate2 q
|
|
||||||
(dateqcons,pdate) | queryIsDate2 dateq || (queryIsDate dateq && date2_ opts) = (Date2, postingDate2)
|
|
||||||
| otherwise = (Date, postingDate)
|
|
||||||
requestedspan = dbg1 "requestedspan" $ queryDateSpan' q -- span specified by -b/-e/-p options and query args
|
|
||||||
requestedspan' = dbg1 "requestedspan'" $ requestedspan `spanDefaultsFrom` journalDateSpan ({-date2_ opts-} False) j -- if open-ended, close it using the journal's end dates
|
|
||||||
intervalspans = dbg1 "intervalspans" $ splitSpan (intervalFromOpts opts) requestedspan' -- interval spans enclosing it
|
|
||||||
reportstart = dbg1 "reportstart" $ maybe Nothing spanStart $ headMay intervalspans
|
|
||||||
reportend = dbg1 "reportend" $ maybe Nothing spanEnd $ lastMay intervalspans
|
|
||||||
reportspan = dbg1 "reportspan" $ DateSpan reportstart reportend -- the requested span enlarged to a whole number of intervals
|
|
||||||
beforestartq = dbg1 "beforestartq" $ dateqcons $ DateSpan Nothing reportstart
|
|
||||||
beforeendq = dbg1 "beforeendq" $ dateqcons $ DateSpan Nothing reportend
|
|
||||||
reportq = dbg1 "reportq" $ depthless $ And [datelessq, beforeendq] -- user's query with no start date, end date on an interval boundary and no depth limit
|
|
||||||
|
|
||||||
pstoend =
|
|
||||||
dbg1 "ps4" $ sortBy (comparing pdate) $ -- sort postings by date (or date2)
|
|
||||||
dbg1 "ps3" $ map (filterPostingAmount symq) $ -- remove amount parts which the query's cur: terms would exclude
|
|
||||||
dbg1 "ps2" $ (if related_ opts then concatMap relatedPostings else id) $ -- with -r, replace each with its sibling postings
|
|
||||||
dbg1 "ps1" $ filter (reportq `matchesPosting`) $ -- filter postings by the query, including before the report start date, ignoring depth
|
|
||||||
journalPostings $ journalSelectingAmountFromOpts opts j
|
|
||||||
(precedingps, reportps) = dbg1 "precedingps, reportps" $ span (beforestartq `matchesPosting`) pstoend
|
|
||||||
|
|
||||||
showempty = empty_ opts || average_ opts
|
|
||||||
-- displayexpr = display_ opts -- XXX
|
|
||||||
interval = intervalFromOpts opts -- XXX
|
|
||||||
|
|
||||||
|
reportspan = adjustReportDates opts q j
|
||||||
whichdate = whichDateFromOpts opts
|
whichdate = whichDateFromOpts opts
|
||||||
itemps | interval == NoInterval = map (,Nothing) reportps
|
depth = queryDepth q
|
||||||
| otherwise = summarisePostingsByInterval interval whichdate depth showempty reportspan reportps
|
|
||||||
items = dbg1 "items" $ postingsReportItems itemps (nullposting,Nothing) whichdate depth startbal runningcalc 1
|
-- postings to be included in the report, and similarly-matched postings before the report start date
|
||||||
|
(precedingps, reportps) = matchedPostingsBeforeAndDuring opts q j reportspan
|
||||||
|
|
||||||
|
-- postings or pseudo postings to be displayed
|
||||||
|
displayps | interval == NoInterval = map (,Nothing) reportps
|
||||||
|
| otherwise = summarisePostingsByInterval interval whichdate depth showempty reportspan reportps
|
||||||
|
where
|
||||||
|
interval = intervalFromOpts opts -- XXX
|
||||||
|
showempty = empty_ opts || average_ opts
|
||||||
|
|
||||||
|
-- posting report items ready for display
|
||||||
|
items = dbg1 "postingsReport items" $ postingsReportItems displayps (nullposting,Nothing) whichdate depth startbal runningcalc 1
|
||||||
where
|
where
|
||||||
startbal = if balancetype_ opts == HistoricalBalance then sumPostings precedingps else 0
|
startbal = if balancetype_ opts == HistoricalBalance then sumPostings precedingps else 0
|
||||||
runningcalc | average_ opts = \i avg amt -> avg + (amt - avg) `divideMixedAmount` (fromIntegral i) -- running average
|
runningcalc | average_ opts = \i avg amt -> avg + (amt - avg) `divideMixedAmount` (fromIntegral i) -- running average
|
||||||
| otherwise = \_ bal amt -> bal + amt -- running total
|
| otherwise = \_ bal amt -> bal + amt -- running total
|
||||||
|
|
||||||
dbg1 s = let p = "postingsReport" in Hledger.Utils.dbg1 (p++" "++s) -- add prefix in debug output
|
|
||||||
-- dbg1 = const id -- exclude from debug output
|
|
||||||
|
|
||||||
totallabel = "Total"
|
totallabel = "Total"
|
||||||
|
|
||||||
|
-- | Adjust report start/end dates to more useful ones based on
|
||||||
|
-- journal data and report intervals. Ie:
|
||||||
|
-- 1. If the start date is unspecified, use the earliest date in the journal (if any)
|
||||||
|
-- 2. If the end date is unspecified, use the latest date in the journal (if any)
|
||||||
|
-- 3. If a report interval is specified, enlarge the dates to enclose whole intervals
|
||||||
|
adjustReportDates :: ReportOpts -> Query -> Journal -> DateSpan
|
||||||
|
adjustReportDates opts q j = reportspan
|
||||||
|
where
|
||||||
|
-- see also multiBalanceReport
|
||||||
|
requestedspan = dbg1 "requestedspan" $ queryDateSpan' q -- span specified by -b/-e/-p options and query args
|
||||||
|
journalspan = dbg1 "journalspan" $ dates `spanUnion` date2s -- earliest and latest dates (or date2s) in the journal
|
||||||
|
where
|
||||||
|
dates = journalDateSpan False j
|
||||||
|
date2s = journalDateSpan True j
|
||||||
|
requestedspanclosed = dbg1 "requestedspanclosed" $ requestedspan `spanDefaultsFrom` journalspan -- if open-ended, close it using the journal's dates (if any)
|
||||||
|
intervalspans = dbg1 "intervalspans" $ splitSpan (intervalFromOpts opts) requestedspanclosed -- get the whole intervals enclosing that
|
||||||
|
mreportstart = dbg1 "reportstart" $ maybe Nothing spanStart $ headMay intervalspans -- start of the first interval, or open ended
|
||||||
|
mreportend = dbg1 "reportend" $ maybe Nothing spanEnd $ lastMay intervalspans -- end of the last interval, or open ended
|
||||||
|
reportspan = dbg1 "reportspan" $ DateSpan mreportstart mreportend -- the requested span enlarged to whole intervals if possible
|
||||||
|
|
||||||
|
-- | Find postings matching a given query, within a given date span,
|
||||||
|
-- and also any similarly-matched postings before that date span.
|
||||||
|
-- Date restrictions and depth restrictions in the query are ignored.
|
||||||
|
-- A helper for the postings report.
|
||||||
|
matchedPostingsBeforeAndDuring :: ReportOpts -> Query -> Journal -> DateSpan -> ([Posting],[Posting])
|
||||||
|
matchedPostingsBeforeAndDuring opts q j (DateSpan mstart mend) =
|
||||||
|
dbg1 "beforeps, duringps" $ span (beforestartq `matchesPosting`) beforeandduringps
|
||||||
|
where
|
||||||
|
beforestartq = dbg1 "beforestartq" $ dateqtype $ DateSpan Nothing mstart
|
||||||
|
beforeandduringps =
|
||||||
|
dbg1 "ps4" $ sortBy (comparing sortdate) $ -- sort postings by date or date2
|
||||||
|
dbg1 "ps3" $ map (filterPostingAmount symq) $ -- remove amount parts which the query's cur: terms would exclude
|
||||||
|
dbg1 "ps2" $ (if related_ opts then concatMap relatedPostings else id) $ -- with -r, replace each with its sibling postings
|
||||||
|
dbg1 "ps1" $ filter (beforeandduringq `matchesPosting`) $ -- filter postings by the query, with no start date or depth limit
|
||||||
|
journalPostings $ journalSelectingAmountFromOpts opts j
|
||||||
|
where
|
||||||
|
beforeandduringq = dbg1 "beforeandduringq" $ And [depthless $ dateless q, beforeendq]
|
||||||
|
where
|
||||||
|
depthless = filterQuery (not . queryIsDepth)
|
||||||
|
dateless = filterQuery (not . queryIsDateOrDate2)
|
||||||
|
beforeendq = dateqtype $ DateSpan Nothing mend
|
||||||
|
sortdate = if date2_ opts then postingDate2 else postingDate
|
||||||
|
symq = dbg1 "symq" $ filterQuery queryIsSym q
|
||||||
|
dateqtype
|
||||||
|
| queryIsDate2 dateq || (queryIsDate dateq && date2_ opts) = Date2
|
||||||
|
-- | queryIsDate2 dateq = Date2
|
||||||
|
-- | queryIsDate2 dateq || date2_ opts = Date2
|
||||||
|
| otherwise = Date
|
||||||
|
where
|
||||||
|
dateq = dbg1 "dateq" $ filterQuery queryIsDateOrDate2 $ dbg1 "q" q -- XXX confused by multiple date:/date2: ?
|
||||||
|
|
||||||
-- | Generate postings report line items from a list of postings or (with
|
-- | Generate postings report line items from a list of postings or (with
|
||||||
-- non-Nothing dates attached) summary postings.
|
-- non-Nothing dates attached) summary postings.
|
||||||
postingsReportItems :: [(Posting,Maybe Day)] -> (Posting,Maybe Day) -> WhichDate -> Int -> MixedAmount -> (Int -> MixedAmount -> MixedAmount -> MixedAmount) -> Int -> [PostingsReportItem]
|
postingsReportItems :: [(Posting,Maybe Day)] -> (Posting,Maybe Day) -> WhichDate -> Int -> MixedAmount -> (Int -> MixedAmount -> MixedAmount -> MixedAmount) -> Int -> [PostingsReportItem]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user