make -V do --value=end in multiperiod reports (#329)

This commit is contained in:
Simon Michael 2019-05-24 03:49:01 -07:00
parent 53ac950628
commit aa99743096
11 changed files with 114 additions and 70 deletions

View File

@ -72,6 +72,7 @@ balanceReport ropts@ReportOpts{..} q j =
dbg1 s = let p = "balanceReport" in Hledger.Utils.dbg1 (p++" "++s) -- add prefix in debug output
today = fromMaybe (error' "balanceReport: ReportOpts today_ is unset so could not satisfy --value=now") today_
multiperiod = interval_ /= NoInterval
-- Get all the summed accounts & balances, according to the query, as an account tree.
-- If doing cost valuation, amounts will be converted to cost first.
@ -83,10 +84,13 @@ balanceReport ropts@ReportOpts{..} q j =
valueaccount a@Account{..} = a{aebalance=val aebalance, aibalance=val aibalance}
where
val = case value_ of
Nothing -> id
Just (AtCost _mc) -> id
Just (AtEnd _mc) -> mixedAmountValue prices periodlastday
Just (AtNow _mc) -> mixedAmountValue prices today
Just (AtDefault _mc) | multiperiod -> mixedAmountValue prices periodlastday
Just (AtDefault _mc) -> mixedAmountValue prices today
Just (AtDate d _mc) -> mixedAmountValue prices d
_ -> id
where
-- prices are in parse order - sort into date then parse order,
-- & reversed for quick lookup of the latest price.

View File

@ -273,12 +273,16 @@ budgetReportAsText ropts@ReportOpts{..} budgetr@(PeriodicReport ( _, rows, _)) =
title ++ "\n\n" ++
tableAsText ropts showcell (maybetranspose $ budgetReportAsTable ropts budgetr)
where
multiperiod = interval_ /= NoInterval
title = printf "Budget performance in %s%s:"
(showDateSpan $ budgetReportSpan budgetr)
(case value_ of
Just (AtCost _mc) -> ", valued at cost"
Just (AtEnd _mc) -> ", valued at period ends"
Just (AtNow _mc) -> ", current value"
-- XXX duplicates the above
Just (AtDefault _mc) | multiperiod -> ", valued at period ends"
Just (AtDefault _mc) -> ", current value"
Just (AtDate d _mc) -> ", valued at "++showDate d
Nothing -> "")
actualwidth =

View File

@ -42,13 +42,19 @@ entriesReport ropts@ReportOpts{..} q j@Journal{..} =
pvalue p@Posting{..} = case value_ of
Nothing -> p
Just (AtCost _mc) -> postingToCost (journalCommodityStyles j) p
Just (AtEnd _mc) -> postingValue jmarketprices (fromMaybe (postingDate p) -- XXX shouldn't happen
mperiodorjournallastday) p
Just (AtNow _mc) -> postingValue jmarketprices (
case today_ of Just d -> d
Nothing -> error' "erValue: ReportOpts today_ is unset so could not satisfy --value=now") p
Just (AtEnd _mc) -> valueend p
Just (AtNow _mc) -> valuenow p
Just (AtDefault _mc) -> valuenow p
Just (AtDate d _mc) -> postingValue jmarketprices d p
where
valueend p = postingValue jmarketprices (
fromMaybe (postingDate p) -- XXX shouldn't happen
mperiodorjournallastday
) p
valuenow p = postingValue jmarketprices (
case today_ of Just d -> d
Nothing -> error' "erValue: ReportOpts today_ is unset so could not satisfy --value=now"
) p
mperiodorjournallastday = mperiodlastday <|> journalEndDate False j
where
-- The last day of the report period.

View File

@ -261,6 +261,7 @@ multiBalanceReport ropts@ReportOpts{..} q j@Journal{..} =
-- One row per account, with account name info, row amounts, row total and row average.
-- Row amounts are converted to value if that has been requested.
-- Row total/average are always simply the sum/average of the row amounts.
multiperiod = interval_ /= NoInterval
rows :: [MultiBalanceReportRow] =
dbg1 "rows" $
[(a, accountLeafName a, accountNameLevel a, valuedrowbals, rowtot, rowavg)
@ -273,12 +274,16 @@ multiBalanceReport ropts@ReportOpts{..} q j@Journal{..} =
CumulativeChange -> drop 1 $ scanl (+) 0 changes
HistoricalBalance -> drop 1 $ scanl (+) (startingBalanceFor a) changes
-- The row amounts valued according to --value if needed.
, let rowbalsendvalue = [mixedAmountValue prices periodlastday amt | (amt,periodlastday) <- zip rowbals lastdays]
, let rowbalsdatevalue d = [mixedAmountValue prices d amt | amt <- rowbals]
, let valuedrowbals = dbg1 "valuedrowbals" $ case value_ of
Just (AtCost _mc) -> rowbals -- cost valuation was handled earlier
Just (AtEnd _mc) -> [mixedAmountValue prices periodlastday amt | (amt,periodlastday) <- zip rowbals lastdays]
Just (AtNow _mc) -> [mixedAmountValue prices today amt | amt <- rowbals]
Just (AtDate d _mc) -> [mixedAmountValue prices d amt | amt <- rowbals]
Nothing -> rowbals
Just (AtCost _mc) -> rowbals -- cost valuation was handled earlier
Just (AtEnd _mc) -> rowbalsendvalue
Just (AtNow _mc) -> rowbalsdatevalue today
Just (AtDefault _mc) | multiperiod -> rowbalsendvalue
Just (AtDefault _mc) -> rowbalsdatevalue today
Just (AtDate d _mc) -> rowbalsdatevalue d
-- The total and average for the row, and their values.
-- Total for a cumulative/historical report is always zero.

View File

@ -87,36 +87,44 @@ postingsReport ropts@ReportOpts{..} q j@Journal{..} =
today = fromMaybe (error' "postingsReport: ReportOpts today_ is unset so could not satisfy --value=now") today_
multiperiod = interval_ /= NoInterval
-- Postings or summary pseudo postings to be displayed.
displayps =
let
multiperiod = interval_ /= NoInterval
in
if multiperiod then
let
showempty = empty_ || average_
summaryps = summarisePostingsByInterval interval_ whichdate depth showempty reportspan reportps
in case value_ of
Just (AtEnd _mc) -> [(postingValue jmarketprices periodlastday p , periodend) | (p,periodend) <- summaryps
summarypsendvalue = [(postingValue jmarketprices periodlastday p, periodend) | (p,periodend) <- summaryps
,let periodlastday = maybe
(error' "postingsReport: expected a subperiod end date") -- XXX shouldn't happen
(addDays (-1))
periodend
]
Just (AtNow _mc) -> [(postingValue jmarketprices today p , periodend) | (p,periodend) <- summaryps]
Just (AtDate d _mc) -> [(postingValue jmarketprices d p , periodend) | (p,periodend) <- summaryps]
summarypsdatevalue d = [(postingValue jmarketprices d p, periodend) | (p,periodend) <- summaryps]
in case value_ of
Nothing -> summaryps
Just (AtCost _mc) -> summaryps -- conversion to cost was done earlier
_ -> summaryps
Just (AtEnd _mc) -> summarypsendvalue
Just (AtNow _mc) -> summarypsdatevalue today
Just (AtDefault _mc) | multiperiod -> summarypsendvalue
Just (AtDefault _mc) -> summarypsdatevalue today
Just (AtDate d _mc) -> summarypsdatevalue d
else
let reportperiodlastday =
let
reportperiodlastday =
fromMaybe (error' "postingsReport: expected a non-empty journal") -- XXX shouldn't happen
$ reportPeriodOrJournalLastDay ropts j
reportpsdatevalue d = [(postingValue jmarketprices d p, Nothing) | p <- reportps]
reportpsnovalue = [(p, Nothing) | p <- reportps]
in case value_ of
Nothing -> [(p , Nothing) | p <- reportps]
Just (AtCost _mc) -> [(p , Nothing) | p <- reportps] -- conversion to cost was done earlier
Just (AtEnd _mc) -> [(postingValue jmarketprices reportperiodlastday p, Nothing) | p <- reportps]
Just (AtNow _mc) -> [(postingValue jmarketprices today p , Nothing) | p <- reportps]
Just (AtDate d _mc) -> [(postingValue jmarketprices d p , Nothing) | p <- reportps]
Nothing -> reportpsnovalue
Just (AtCost _mc) -> reportpsnovalue -- conversion to cost was done earlier
Just (AtEnd _mc) -> reportpsdatevalue reportperiodlastday
Just (AtNow _mc) -> reportpsdatevalue today
Just (AtDefault _mc) | multiperiod -> reportpsdatevalue reportperiodlastday
Just (AtDefault _mc) -> reportpsdatevalue today
Just (AtDate d _mc) -> reportpsdatevalue d
-- posting report items ready for display
items = dbg1 "postingsReport items" $ postingsReportItems displayps (nullposting,Nothing) whichdate depth valuedstartbal runningcalc startnum
@ -128,20 +136,24 @@ postingsReport ropts@ReportOpts{..} q j@Journal{..} =
startbal | average_ = if historical then precedingavg else 0
| otherwise = if historical then precedingsum else 0
-- For --value=end/now/DATE, convert the initial running total/average to value.
startbaldatevalue d = mixedAmountValue prices d startbal
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
valuedstartbal = case value_ of
Nothing -> startbal
Just (AtCost _mc) -> startbal -- conversion to cost was done earlier
Just (AtEnd _mc) -> mixedAmountValue prices daybeforereportstart startbal
Just (AtNow _mc) -> mixedAmountValue prices today startbal
Just (AtDate d _mc) -> mixedAmountValue prices d startbal
Just (AtEnd _mc) -> startbaldatevalue daybeforereportstart
Just (AtNow _mc) -> startbaldatevalue today
Just (AtDefault _mc) | multiperiod -> startbaldatevalue daybeforereportstart
Just (AtDefault _mc) -> startbaldatevalue today
Just (AtDate d _mc) -> startbaldatevalue d
where
daybeforereportstart = maybe
(error' "postingsReport: expected a non-empty journal") -- XXX shouldn't happen
(addDays (-1))
$ reportPeriodOrJournalStart ropts j
-- prices are in parse order - sort into date then parse order,
-- & reversed for quick lookup of the latest price.
prices = reverse $ sortOn mpdate jmarketprices
startnum = if historical then length precedingps + 1 else 1
runningcalc = registerRunningCalculationFn ropts

View File

@ -85,6 +85,7 @@ data ValuationType =
| AtEnd (Maybe CommoditySymbol) -- ^ convert to default valuation commodity or given commodity, using market prices at period end(s)
| AtNow (Maybe CommoditySymbol) -- ^ convert to default valuation commodity or given commodity, using current market prices
| AtDate Day (Maybe CommoditySymbol) -- ^ convert to default valuation commodity or given commodity, using market prices on some date
| AtDefault (Maybe CommoditySymbol) -- ^ works like AtNow in single period reports, like AtEnd in multiperiod reports
deriving (Show,Data,Eq) -- Typeable
-- instance Default ValuationType where def = AtNow Nothing
@ -349,7 +350,7 @@ valuationTypeFromRawOpts = lastDef Nothing . filter isJust . map valuationfromra
where
valuationfromrawopt (n,v)
| n == "B" = Just $ AtCost Nothing
| n == "V" = Just $ AtNow Nothing -- TODO: if multiperiod then AtEnd Nothing
| n == "V" = Just $ AtDefault Nothing
| n == "value" = Just $ valuation v
| otherwise = Nothing
valuation v

View File

@ -576,6 +576,7 @@ multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
multiBalanceReportAsText ropts@ReportOpts{..} r =
title ++ "\n\n" ++ (balanceReportTableAsText ropts $ balanceReportAsTable ropts r)
where
multiperiod = interval_ /= NoInterval
title = printf "%s in %s%s:"
(case balancetype_ of
PeriodChange -> "Balance changes"
@ -586,6 +587,9 @@ multiBalanceReportAsText ropts@ReportOpts{..} r =
Just (AtCost _mc) -> ", valued at cost"
Just (AtEnd _mc) -> ", valued at period ends"
Just (AtNow _mc) -> ", current value"
-- XXX duplicates the above
Just (AtDefault _mc) | multiperiod -> ", valued at period ends"
Just (AtDefault _mc) -> ", current value"
Just (AtDate d _mc) -> ", valued at "++showDate d
Nothing -> "")

View File

@ -140,10 +140,13 @@ compoundBalanceCommand CompoundBalanceCommandSpec{..} opts@CliOpts{reportopts_=r
PeriodChange -> "(Balance Changes)"
CumulativeChange -> "(Cumulative Ending Balances)"
HistoricalBalance -> "(Historical Ending Balances)"
multiperiod = interval_ /= NoInterval
valuation = case value_ of
Just (AtCost _mc) -> ", valued at cost"
Just (AtEnd _mc) -> ", valued at period ends"
Just (AtNow _mc) -> ", current value"
Just (AtDefault _mc) | multiperiod -> ", valued at period ends"
Just (AtDefault _mc) -> ", current value"
Just (AtDate d _mc) -> ", valued at "++showDate d
Nothing -> ""

View File

@ -447,13 +447,18 @@ $ hledger balance --pivot member acct:.
The `-B/--cost` flag converts amounts to their cost at transaction time,
if they have a [transaction price](/journal.html#transaction-prices) specified.
This flag is equivalent to `--value=cost`, described below.
## Market value
The `-V/--market` flag converts reported amounts to their market value in another commodity.
It uses the commodity referenced in the latest [market price](journal.html#market-prices) (P directive)
dated on or before the valuation date. The default valuation date is today.
For example:
It uses the default valuation commodity referenced in the latest [market price](journal.html#market-prices) (P directive)
dated on or before the default valuation date, which is:
- today for single period reports (equivalent to `--value=now`)
- the end of each subperiod for multiperiod reports (ie, reports with a [report interval](#report-intervals)) (equivalent to `--value=end`).
A quick example of `-V`:
```journal
# one euro is worth this many dollars from nov 1
@ -495,8 +500,8 @@ You can control valuation more precisely with the `--value` option.
--value=TYPE which type of valuation should be done ? cost|end|now|YYYY-MM-DD
The argument is one of the keywords shown, or their first letter, or a custom date.
The precise effect of the keywords is command-specific, but here is their general meaning:
TYPE is one of the keywords shown, or their first letter, or a custom date.
Their meanings:
`--value=cost` (or `c`)
: Convert amounts to cost, using the prices recorded in transactions.

View File

@ -338,7 +338,7 @@ P 2018/01/26 SHARE €10
assets:bank
$ hledger -f - bal -M --budget --cumulative --forecast -V
Budget performance in 2018/05/01-2018/06/30, current value:
Budget performance in 2018/05/01-2018/06/30, valued at period ends:
|| May Jun
================++==========================================

View File

@ -223,7 +223,7 @@ $ hledger -f- reg --value=now
2000/02/01 (a) 4 B 8 B
2000/03/01 (a) 4 B 12 B
# 18. register report valued at default date (same as above)
# 18. single-period register report valued at default date (same as --value=now)
$ hledger -f- reg -V
2000/01/01 (a) 4 B 4 B
2000/02/01 (a) 4 B 8 B
@ -314,11 +314,11 @@ $ hledger -f- reg --value=now -M
2000/02 a 4 B 8 B
2000/03 a 4 B 12 B
# 26. periodic register report valued at default date (same as above)
# 26. periodic register report valued at default date (same as --value=end)
$ hledger -f- reg -V -M
2000/01 a 4 B 4 B
2000/02 a 4 B 8 B
2000/03 a 4 B 12 B
2000/01 a 5 B 5 B
2000/02 a 2 B 7 B
2000/03 a 3 B 10 B
# balance
@ -338,7 +338,7 @@ $ hledger -f- bal -N --value=2000-01-15
$ hledger -f- bal -N --value=now
12 B a
# 31. single column balance report valued at default date (same as above)
# 31. single column balance report valued at default date (same as --value=now)
$ hledger -f- bal -N -V
12 B a
@ -394,15 +394,15 @@ Balance changes in 2000q1, current value:
---++---------------
|| 4 B 4 B 4 B
# 37. multicolumn balance report valued at default date (same as above)
# 37. multicolumn balance report valued at default date (same as --value=end)
$ hledger -f- bal -M -V
Balance changes in 2000q1, current value:
Balance changes in 2000q1, valued at period ends:
|| Jan Feb Mar
===++===============
a || 4 B 4 B 4 B
a || 5 B 2 B 3 B
---++---------------
|| 4 B 4 B 4 B
|| 5 B 2 B 3 B
# balance, periodic, with -H (starting balance and accumulating across periods)