From 7306e61646186f023c3af84c4f3e04e028039df7 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Fri, 26 Apr 2019 11:45:51 -0700 Subject: [PATCH] bal: support --value-at in single column balance reports --- hledger-lib/Hledger/Reports/BalanceReport.hs | 52 +++++++++++++------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/hledger-lib/Hledger/Reports/BalanceReport.hs b/hledger-lib/Hledger/Reports/BalanceReport.hs index 1de44f9af..8b31ec079 100644 --- a/hledger-lib/Hledger/Reports/BalanceReport.hs +++ b/hledger-lib/Hledger/Reports/BalanceReport.hs @@ -4,7 +4,7 @@ Balance report, used by the balance command. -} -{-# LANGUAGE FlexibleInstances, ScopedTypeVariables, OverloadedStrings #-} +{-# LANGUAGE FlexibleInstances, RecordWildCards, ScopedTypeVariables, OverloadedStrings #-} module Hledger.Reports.BalanceReport ( BalanceReport, @@ -172,25 +172,41 @@ brNegate (is, tot) = (map brItemNegate is, -tot) -- | Convert all the posting amounts in a BalanceReport to their -- default valuation commodities. This means using the Journal's most -- recent applicable market prices before the valuation date. --- The valuation date is the specified report end date if any, --- otherwise the current date, otherwise the journal's end date. +-- The valuation date is set with --value-at and can be: +-- each posting's date, +-- the last day in the report period (or in the journal if no period, +-- or gives an error if journal is empty - shouldn't happen), +-- or today's date (gives an error if today_ is not set in ReportOpts), +-- or a specified date. brValue :: ReportOpts -> Journal -> BalanceReport -> BalanceReport -brValue ropts j r = - let mvaluationdate = periodEnd (period_ ropts) <|> today_ ropts <|> journalEndDate False j - in case mvaluationdate of - Nothing -> r - Just d -> r' - where - -- prices are in parse order - sort into date then parse order, - -- & reversed for quick lookup of the latest price. - prices = reverse $ sortOn mpdate $ jmarketprices j - (items,total) = r - r' = - dbg8 "market prices" prices `seq` - dbg8 "valuation date" d `seq` - dbg8 "brValue" - ([(n, n', i, mixedAmountValue prices d a) |(n,n',i,a) <- items], mixedAmountValue prices d total) +brValue ropts@ReportOpts{..} j (items, total) = + ([ (n, n', i, mixedAmountValue prices d a) | (n,n',i,a) <- items ] + ,mixedAmountValue prices d total + ) + where + -- prices are in parse order - sort into date then parse order, + -- & reversed for quick lookup of the latest price. + prices = reverse $ sortOn mpdate $ jmarketprices j + d = case value_at_ of + AtTransaction -> error' "sorry, --value-at=transaction is not yet supported with balance reports" -- XXX + AtPeriod -> fromMaybe (error' "brValue: expected a non-empty journal") mperiodorjournallastday -- XXX shouldn't happen + AtNow -> case today_ of + Just d -> d + Nothing -> error' "brValue: ReportOpts today_ is unset so could not satisfy --value-at=now" + AtDate d -> d + -- Get the last day of the report period. + -- Will be Nothing if no report period is specified, or also + -- if ReportOpts does not have today_ set, since we need that + -- to get the report period robustly. + mperiodlastday :: Maybe Day = do + t <- today_ + let q = queryFromOpts t ropts + qend <- queryEndDate False q + return $ addDays (-1) qend + + mperiodorjournallastday = mperiodlastday <|> journalEndDate False j + -- -- | Find the best commodity to convert to when asked to show the -- -- market value of this commodity on the given date. That is, the one -- -- in which it has most recently been market-priced, ie the commodity