make -V do --value=end in multiperiod reports (#329)
This commit is contained in:
parent
53ac950628
commit
aa99743096
@ -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
|
||||
Just (AtEnd _mc) -> mixedAmountValue prices periodlastday
|
||||
Just (AtNow _mc) -> mixedAmountValue prices today
|
||||
Just (AtDate d _mc) -> mixedAmountValue prices d
|
||||
_ -> id
|
||||
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
|
||||
where
|
||||
-- prices are in parse order - sort into date then parse order,
|
||||
-- & reversed for quick lookup of the latest price.
|
||||
|
||||
@ -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 =
|
||||
|
||||
@ -40,15 +40,21 @@ entriesReport ropts@ReportOpts{..} q j@Journal{..} =
|
||||
datefn = transactionDateFn ropts
|
||||
tvalue t@Transaction{..} = t{tpostings=map pvalue tpostings}
|
||||
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 (AtDate d _mc) -> postingValue jmarketprices d p
|
||||
Nothing -> p
|
||||
Just (AtCost _mc) -> postingToCost (journalCommodityStyles j) 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.
|
||||
|
||||
@ -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
|
||||
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.
|
||||
|
||||
@ -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
|
||||
,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]
|
||||
Just (AtCost _mc) -> summaryps -- conversion to cost was done earlier
|
||||
_ -> summaryps
|
||||
else
|
||||
let reportperiodlastday =
|
||||
fromMaybe (error' "postingsReport: expected a non-empty journal") -- XXX shouldn't happen
|
||||
$ reportPeriodOrJournalLastDay ropts j
|
||||
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]
|
||||
if multiperiod then
|
||||
let
|
||||
showempty = empty_ || average_
|
||||
summaryps = summarisePostingsByInterval interval_ whichdate depth showempty reportspan reportps
|
||||
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
|
||||
]
|
||||
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
|
||||
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 =
|
||||
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 -> 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
|
||||
Nothing -> startbal
|
||||
Just (AtCost _mc) -> startbal -- conversion to cost was done earlier
|
||||
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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 -> "")
|
||||
|
||||
|
||||
@ -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 -> ""
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
================++==========================================
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user