diff --git a/hledger-lib/Hledger/Reports/PostingsReport.hs b/hledger-lib/Hledger/Reports/PostingsReport.hs index f5f553de2..f90ddce9c 100644 --- a/hledger-lib/Hledger/Reports/PostingsReport.hs +++ b/hledger-lib/Hledger/Reports/PostingsReport.hs @@ -9,6 +9,7 @@ module Hledger.Reports.PostingsReport ( PostingsReport, PostingsReportItem, postingsReport, + postingsReportValue, mkpostingsReportItem, -- * Tests @@ -28,6 +29,7 @@ import Test.HUnit import Hledger.Data import Hledger.Query import Hledger.Utils +import Hledger.Reports.BalanceReport import Hledger.Reports.ReportOptions @@ -87,6 +89,31 @@ postingsReport opts q j = (totallabel, items) totallabel = "Total" +-- | Convert all the amounts in a postings report to +-- their value on the given date in their default valuation +-- commodities. +postingsReportValue :: Journal -> Day -> PostingsReport -> PostingsReport +postingsReportValue j d r = r' + where + (label,items) = r + r' = dbg8 "postingsReportValue" $ + (label,[(pb,pe,pd,postingValue j d pp,mixedAmountValue j d a) | (pb,pe,pd,pp,a) <- items]) + +postingValue :: Journal -> Day -> Posting -> Posting +postingValue j d p = p' + where + Posting {pamount = pa, pbalanceassertion = pb, ptransaction = pt} = p + p' = p{pamount = mixedAmountValue j d pa + ,pbalanceassertion = mixedAmountValue j d <$> pb + ,ptransaction = transactionValue j d <$> pt + } + +transactionValue :: Journal -> Day -> Transaction -> Transaction +transactionValue j d t = t' + where + Transaction {tpostings = tp} = t + t' = t{tpostings = map (postingValue j d) tp} + -- | 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) diff --git a/hledger/Hledger/Cli/Balancesheet.hs b/hledger/Hledger/Cli/Balancesheet.hs index 5709d4b32..6e9622f08 100644 --- a/hledger/Hledger/Cli/Balancesheet.hs +++ b/hledger/Hledger/Cli/Balancesheet.hs @@ -11,6 +11,7 @@ module Hledger.Cli.Balancesheet ( ,tests_Hledger_Cli_Balancesheet ) where +import Data.Maybe (fromMaybe) import qualified Data.Text.Lazy.IO as LT import System.Console.CmdArgs.Explicit import Test.HUnit @@ -28,6 +29,7 @@ balancesheetmode = (defCommandMode $ ["balancesheet"]++aliases) { groupUnnamed = [ flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list" ,flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "flat mode: omit N leading account name parts" + ,flagNone ["value","V"] (setboolopt "value") "show amounts as their current market value in their default valuation commodity" ] ,groupHidden = [] ,groupNamed = [generalflagsgroup1] @@ -41,18 +43,23 @@ balancesheet CliOpts{reportopts_=ropts} j = do -- let lines = case lineFormatFromOpts ropts of Left err, Right ... d <- getCurrentDay let q = queryFromOpts d (withoutBeginDate ropts) + valuedate = fromMaybe d $ queryEndDate False $ queryFromOpts d ropts assetreport@(_,assets) = balanceReport ropts (And [q, journalAssetAccountQuery j]) j liabilityreport@(_,liabilities) = balanceReport ropts (And [q, journalLiabilityAccountQuery j]) j total = assets + liabilities + convertReport | value_ ropts = balanceReportValue j valuedate + | otherwise = id + convertTotal | value_ ropts = mixedAmountValue j valuedate + | otherwise = id LT.putStr $ [lt|Balance Sheet Assets: -#{balanceReportAsText ropts assetreport} +#{balanceReportAsText ropts (convertReport assetreport)} Liabilities: -#{balanceReportAsText ropts liabilityreport} +#{balanceReportAsText ropts (convertReport liabilityreport)} Total: -------------------- -#{padleft 20 $ showMixedAmountWithoutPrice total} +#{padleft 20 $ showMixedAmountWithoutPrice (convertTotal total)} |] withoutBeginDate :: ReportOpts -> ReportOpts diff --git a/hledger/Hledger/Cli/Cashflow.hs b/hledger/Hledger/Cli/Cashflow.hs index 288ec178d..497eafcd9 100644 --- a/hledger/Hledger/Cli/Cashflow.hs +++ b/hledger/Hledger/Cli/Cashflow.hs @@ -14,6 +14,7 @@ module Hledger.Cli.Cashflow ( ,tests_Hledger_Cli_Cashflow ) where +import Data.Maybe (fromMaybe) import qualified Data.Text.Lazy.IO as LT import System.Console.CmdArgs.Explicit import Test.HUnit @@ -31,6 +32,7 @@ cashflowmode = (defCommandMode ["cashflow","cf"]) { groupUnnamed = [ flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list" ,flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "flat mode: omit N leading account name parts" + ,flagNone ["value","V"] (setboolopt "value") "show amounts as their current market value in their default valuation commodity" ] ,groupHidden = [] ,groupNamed = [generalflagsgroup1] @@ -43,18 +45,23 @@ cashflow CliOpts{reportopts_=ropts} j = do -- let lines = case lineFormatFromOpts ropts of Left err, Right ... d <- getCurrentDay let q = queryFromOpts d ropts + valuedate = fromMaybe d $ queryEndDate False $ queryFromOpts d ropts cashreport@(_,total) = balanceReport ropts (And [q, journalCashAccountQuery j]) j -- operatingreport@(_,operating) = balanceReport ropts (And [q, journalOperatingAccountMatcher j]) j -- investingreport@(_,investing) = balanceReport ropts (And [q, journalInvestingAccountMatcher j]) j -- financingreport@(_,financing) = balanceReport ropts (And [q, journalFinancingAccountMatcher j]) j -- total = operating + investing + financing + convertReport | value_ ropts = balanceReportValue j valuedate + | otherwise = id + convertTotal | value_ ropts = mixedAmountValue j valuedate + | otherwise = id LT.putStr $ [lt|Cashflow Statement Cash flows: -#{balanceReportAsText ropts cashreport} +#{balanceReportAsText ropts (convertReport cashreport)} Total: -------------------- -#{padleft 20 $ showMixedAmountWithoutPrice total} +#{padleft 20 $ showMixedAmountWithoutPrice (convertTotal total)} |] tests_Hledger_Cli_Cashflow :: Test diff --git a/hledger/Hledger/Cli/Incomestatement.hs b/hledger/Hledger/Cli/Incomestatement.hs index b36cec3ab..31bf9b330 100644 --- a/hledger/Hledger/Cli/Incomestatement.hs +++ b/hledger/Hledger/Cli/Incomestatement.hs @@ -11,6 +11,7 @@ module Hledger.Cli.Incomestatement ( ,tests_Hledger_Cli_Incomestatement ) where +import Data.Maybe (fromMaybe) import qualified Data.Text.Lazy.IO as LT import System.Console.CmdArgs.Explicit import Test.HUnit @@ -28,6 +29,7 @@ incomestatementmode = (defCommandMode $ ["incomestatement"]++aliases) { groupUnnamed = [ flagNone ["flat"] (\opts -> setboolopt "flat" opts) "show accounts as a list" ,flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "flat mode: omit N leading account name parts" + ,flagNone ["value","V"] (setboolopt "value") "show amounts as their current market value in their default valuation commodity" ] ,groupHidden = [] ,groupNamed = [generalflagsgroup1] @@ -40,18 +42,23 @@ incomestatement :: CliOpts -> Journal -> IO () incomestatement CliOpts{reportopts_=ropts} j = do d <- getCurrentDay let q = queryFromOpts d ropts + valuedate = fromMaybe d $ queryEndDate False $ queryFromOpts d ropts incomereport@(_,income) = balanceReport ropts (And [q, journalIncomeAccountQuery j]) j expensereport@(_,expenses) = balanceReport ropts (And [q, journalExpenseAccountQuery j]) j total = income + expenses + convertReport | value_ ropts = balanceReportValue j valuedate + | otherwise = id + convertTotal | value_ ropts = mixedAmountValue j valuedate + | otherwise = id LT.putStr $ [lt|Income Statement Revenues: -#{balanceReportAsText ropts incomereport} +#{balanceReportAsText ropts (convertReport incomereport)} Expenses: -#{balanceReportAsText ropts expensereport} +#{balanceReportAsText ropts (convertReport expensereport)} Total: -------------------- -#{padleft 20 $ showMixedAmountWithoutPrice total} +#{padleft 20 $ showMixedAmountWithoutPrice (convertTotal total)} |] tests_Hledger_Cli_Incomestatement :: Test diff --git a/hledger/Hledger/Cli/Register.hs b/hledger/Hledger/Cli/Register.hs index 28b8e4470..0062a701f 100644 --- a/hledger/Hledger/Cli/Register.hs +++ b/hledger/Hledger/Cli/Register.hs @@ -39,6 +39,7 @@ registermode = (defCommandMode $ ["register"] ++ aliases) { ,flagNone ["average","A"] (\opts -> setboolopt "average" opts) "show running average of posting amounts instead of total (implies --empty)" ,flagNone ["related","r"] (\opts -> setboolopt "related" opts) "show postings' siblings instead" + ,flagNone ["value","V"] (setboolopt "value") "show amounts as their current market value in their default valuation commodity" ,flagReq ["width","w"] (\s opts -> Right $ setopt "width" s opts) "N" ("set output width (default: " ++ #ifdef mingw32_HOST_OS @@ -61,9 +62,12 @@ register :: CliOpts -> Journal -> IO () register opts@CliOpts{reportopts_=ropts} j = do d <- getCurrentDay let fmt = outputFormatFromOpts opts - render | fmt=="csv" = const ((++"\n") . printCSV . postingsReportAsCsv) - | otherwise = postingsReportAsText - writeOutput opts $ render opts $ postingsReport ropts (queryFromOpts d ropts) j + valuedate = fromMaybe d $ queryEndDate False $ queryFromOpts d ropts + convert | value_ ropts = postingsReportValue j valuedate + | otherwise = id + render | fmt=="csv" = const ((++"\n") . printCSV . postingsReportAsCsv) + | otherwise = postingsReportAsText + writeOutput opts $ render opts $ convert $ postingsReport ropts (queryFromOpts d ropts) j postingsReportAsCsv :: PostingsReport -> CSV postingsReportAsCsv (_,is) =