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 | ||||
|                       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. | ||||
|  | ||||
| @ -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 = | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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