Skip to content

Commit

Permalink
Adding "--value"/"-V" option for balancesheet/incomestatement/cashflo…
Browse files Browse the repository at this point in the history
…w and register (#361)

* Added --value options for specialized balance ouputs balancesheet, incomestatement, cashflow

* --value option for 'register' command
lib: postingsValue to convert posting amounts to market value
  • Loading branch information
mstksg authored and simonmichael committed Dec 31, 2016
1 parent 419f5f2 commit b935cd2
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 11 deletions.
27 changes: 27 additions & 0 deletions hledger-lib/Hledger/Reports/PostingsReport.hs
Expand Up @@ -9,6 +9,7 @@ module Hledger.Reports.PostingsReport (
PostingsReport,
PostingsReportItem,
postingsReport,
postingsReportValue,
mkpostingsReportItem,

-- * Tests
Expand All @@ -28,6 +29,7 @@ import Test.HUnit
import Hledger.Data
import Hledger.Query
import Hledger.Utils
import Hledger.Reports.BalanceReport
import Hledger.Reports.ReportOptions


Expand Down Expand Up @@ -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)
Expand Down
13 changes: 10 additions & 3 deletions hledger/Hledger/Cli/Balancesheet.hs
Expand Up @@ -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
Expand All @@ -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]
Expand All @@ -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
Expand Down
11 changes: 9 additions & 2 deletions hledger/Hledger/Cli/Cashflow.hs
Expand Up @@ -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
Expand All @@ -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]
Expand All @@ -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
Expand Down
13 changes: 10 additions & 3 deletions hledger/Hledger/Cli/Incomestatement.hs
Expand Up @@ -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
Expand All @@ -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]
Expand All @@ -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
Expand Down
10 changes: 7 additions & 3 deletions hledger/Hledger/Cli/Register.hs
Expand Up @@ -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
Expand All @@ -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) =
Expand Down

0 comments on commit b935cd2

Please sign in to comment.