diff --git a/hledger-lib/Hledger/Reports/BalanceReport.hs b/hledger-lib/Hledger/Reports/BalanceReport.hs index 1f4b99a10..99581e232 100644 --- a/hledger-lib/Hledger/Reports/BalanceReport.hs +++ b/hledger-lib/Hledger/Reports/BalanceReport.hs @@ -10,6 +10,8 @@ module Hledger.Reports.BalanceReport ( BalanceReportItem, RenderableAccountName, balanceReport, + balanceReportValue, + mixedAmountValue, flatShowsExclusiveBalance, -- * Tests @@ -17,7 +19,9 @@ module Hledger.Reports.BalanceReport ( ) where +import Data.List (sort) import Data.Maybe +import Data.Time.Calendar import Test.HUnit import Hledger.Data @@ -123,6 +127,41 @@ balanceReportItem opts q a -- items = [(a,a',n, headDef 0 bs) | ((a,a',n), bs) <- mbrrows] -- total = headDef 0 mbrtotals +-- | Convert all the amounts in a single-column balance report to +-- their value on the given date in their default valuation +-- commodities. +balanceReportValue :: Journal -> Day -> BalanceReport -> BalanceReport +balanceReportValue j d r = r' + where + (items,total) = r + r' = ([(n, mixedAmountValue j d a) |(n,a) <- items], mixedAmountValue j d total) + +mixedAmountValue :: Journal -> Day -> MixedAmount -> MixedAmount +mixedAmountValue j d (Mixed as) = Mixed $ map (amountValue j d) as + +-- | Find the market value of this amount on the given date, in it's +-- default valuation commodity, based on historical prices. If no +-- default valuation commodity can be found, the amount is left +-- unchanged. +amountValue :: Journal -> Day -> Amount -> Amount +amountValue j d a = + case commodityValue j d (acommodity a) of + Just v -> v{aquantity=aquantity v * aquantity a + ,aprice=aprice a + } + Nothing -> a + +-- | Find the market value, if known, of one unit of this commodity on +-- the given date, in the commodity in which it has most recently been +-- market-priced (ie the commodity mentioned in the most recent +-- applicable historical price directive before this date). +commodityValue :: Journal -> Day -> Commodity -> Maybe Amount +commodityValue j d c + | null applicableprices = Nothing + | otherwise = Just $ mpamount $ last applicableprices + where + applicableprices = [p | p <- sort $ jmarketprices j, mpcommodity p == c, mpdate p <= d] + tests_balanceReport = let (opts,journal) `gives` r = do diff --git a/hledger-lib/Hledger/Reports/MultiBalanceReports.hs b/hledger-lib/Hledger/Reports/MultiBalanceReports.hs index 443b5419c..5907bc28d 100644 --- a/hledger-lib/Hledger/Reports/MultiBalanceReports.hs +++ b/hledger-lib/Hledger/Reports/MultiBalanceReports.hs @@ -8,7 +8,8 @@ Multi-column balance reports, used by the balance command. module Hledger.Reports.MultiBalanceReports ( MultiBalanceReport(..), MultiBalanceReportRow, - multiBalanceReport + multiBalanceReport, + multiBalanceReportValue -- -- * Tests -- tests_Hledger_Reports_MultiBalanceReport @@ -18,6 +19,7 @@ where import Data.List import Data.Maybe import Data.Ord +import Data.Time.Calendar import Safe -- import Test.HUnit @@ -177,3 +179,16 @@ multiBalanceReport opts q j = MultiBalanceReport (displayspans, items, totalsrow dbg1 s = let p = "multiBalanceReport" in Hledger.Utils.dbg1 (p++" "++s) -- add prefix in this function's debug output -- dbg1 = const id -- exclude this function from debug output +-- | Convert all the amounts in a multi-column balance report to their +-- value on the given date in their default valuation commodities +-- (which are determined as of that date, not the report interval dates). +multiBalanceReportValue :: Journal -> Day -> MultiBalanceReport -> MultiBalanceReport +multiBalanceReportValue j d r = r' + where + MultiBalanceReport (spans, rows, (coltotals, rowtotaltotal, rowavgtotal)) = r + r' = MultiBalanceReport + (spans, + [(n, map convert rowamts, convert rowtotal, convert rowavg) | (n, rowamts, rowtotal, rowavg) <- rows], + (map convert coltotals, convert rowtotaltotal, convert rowavgtotal)) + convert = mixedAmountValue j d + diff --git a/hledger/Hledger/Cli/Balance.hs b/hledger/Hledger/Cli/Balance.hs index 1559147ae..06479bdef 100644 --- a/hledger/Hledger/Cli/Balance.hs +++ b/hledger/Hledger/Cli/Balance.hs @@ -243,8 +243,7 @@ module Hledger.Cli.Balance ( ,tests_Hledger_Cli_Balance ) where -import Data.List (intercalate, sort) -import Data.Time.Calendar (Day) +import Data.List (intercalate) import Data.Maybe (fromMaybe, isJust) import System.Console.CmdArgs.Explicit as C import Text.CSV @@ -316,41 +315,6 @@ balance opts@CliOpts{reportopts_=ropts} j = do -- single-column balance reports --- | Convert all the amounts in a single-column balance report to --- their value on the given date in their default valuation --- commodities. -balanceReportValue :: Journal -> Day -> BalanceReport -> BalanceReport -balanceReportValue j d r = r' - where - (items,total) = r - r' = ([(n, mixedAmountValue j d a) |(n,a) <- items], mixedAmountValue j d total) - -mixedAmountValue :: Journal -> Day -> MixedAmount -> MixedAmount -mixedAmountValue j d (Mixed as) = Mixed $ map (amountValue j d) as - --- | Find the market value of this amount on the given date, in it's --- default valuation commodity, based on historical prices. If no --- default valuation commodity can be found, the amount is left --- unchanged. -amountValue :: Journal -> Day -> Amount -> Amount -amountValue j d a = - case commodityValue j d (acommodity a) of - Just v -> v{aquantity=aquantity v * aquantity a - ,aprice=aprice a - } - Nothing -> a - --- | Find the market value, if known, of one unit of this commodity on --- the given date, in the commodity in which it has most recently been --- market-priced (ie the commodity mentioned in the most recent --- applicable historical price directive before this date). -commodityValue :: Journal -> Day -> Commodity -> Maybe Amount -commodityValue j d c - | null applicableprices = Nothing - | otherwise = Just $ mpamount $ last applicableprices - where - applicableprices = [p | p <- sort $ jmarketprices j, mpcommodity p == c, mpdate p <= d] - -- | 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 @@ -472,19 +436,6 @@ renderComponent1 (acctname, depth, total) (FormatField ljust min max field) = ca -- multi-column balance reports --- | Convert all the amounts in a multi-column balance report to their --- value on the given date in their default valuation commodities --- (which are determined as of that date, not the report interval dates). -multiBalanceReportValue :: Journal -> Day -> MultiBalanceReport -> MultiBalanceReport -multiBalanceReportValue j d r = r' - where - MultiBalanceReport (spans, rows, (coltotals, rowtotaltotal, rowavgtotal)) = r - r' = MultiBalanceReport - (spans, - [(n, map convert rowamts, convert rowtotal, convert rowavg) | (n, rowamts, rowtotal, rowavg) <- rows], - (map convert coltotals, convert rowtotaltotal, convert rowavgtotal)) - convert = mixedAmountValue j d - -- | Render a multi-column balance report as CSV. multiBalanceReportAsCsv :: ReportOpts -> MultiBalanceReport -> CSV multiBalanceReportAsCsv opts (MultiBalanceReport (colspans, items, (coltotals,tot,avg))) =