reg: support --value-at in register reports; cleanups, tests
This commit is contained in:
		
							parent
							
								
									7306e61646
								
							
						
					
					
						commit
						696e3098c8
					
				| @ -44,15 +44,14 @@ entriesReport opts q j = | ||||
| -- | Convert all the posting amounts in an EntriesReport to their | ||||
| -- default valuation commodities. This means using the Journal's most | ||||
| -- recent applicable market prices before the valuation date. | ||||
| -- The valuation date is set with --value-date and can be: | ||||
| -- a custom date; | ||||
| -- the posting date; | ||||
| -- the last day in the report period, or in the journal if no period | ||||
| -- (or the posting date, if journal is empty - shouldn't happen); | ||||
| -- or today's date (gives an error if today_ is not set in ReportOpts). | ||||
| -- The valuation date is set with --value-at and can be: | ||||
| -- each posting's date, | ||||
| -- the last day in the report period (or in the journal if no period, | ||||
| -- or the posting dates if journal is empty - shouldn't happen), | ||||
| -- or today's date (gives an error if today_ is not set in ReportOpts), | ||||
| -- or a specified date. | ||||
| erValue :: ReportOpts -> Journal -> EntriesReport -> EntriesReport | ||||
| erValue ropts@ReportOpts{..} j ts = | ||||
|   map txnvalue ts | ||||
| erValue ropts@ReportOpts{..} j ts = map txnvalue ts | ||||
|   where | ||||
|     txnvalue t@Transaction{..} = t{tpostings=map postingvalue tpostings} | ||||
|     postingvalue p@Posting{..} = p{pamount=mixedAmountValue prices d pamount} | ||||
| @ -78,7 +77,7 @@ erValue ropts@ReportOpts{..} j ts = | ||||
|           AtPeriod      -> fromMaybe (postingDate p) mperiodorjournallastday | ||||
|           AtNow         -> case today_ of | ||||
|                              Just d  -> d | ||||
|                              Nothing -> error' "ReportOpts today_ is unset so could not satisfy --value-at=now" | ||||
|                              Nothing -> error' "erValue: ReportOpts today_ is unset so could not satisfy --value-at=now" | ||||
|           AtDate d      -> d | ||||
| 
 | ||||
| tests_EntriesReport = tests "EntriesReport" [ | ||||
|  | ||||
| @ -275,11 +275,11 @@ multiBalanceReportSpan (MultiBalanceReport (colspans, _, _)) = DateSpan (spanSta | ||||
| -- | Convert all the posting amounts in a MultiBalanceReport to their | ||||
| -- default valuation commodities. This means using the Journal's most | ||||
| -- recent applicable market prices before the valuation date. | ||||
| -- The valuation date is set with --value-date and can be: | ||||
| -- the posting date, | ||||
| -- the last day in the report subperiod, | ||||
| -- today's date (gives an error if today_ is not set in ReportOpts), | ||||
| -- or a custom date. | ||||
| -- The valuation date is set with --value-at and can be: | ||||
| -- each posting's date, | ||||
| -- or the last day in the report subperiod, | ||||
| -- or today's date (gives an error if today_ is not set in ReportOpts), | ||||
| -- or a specified date. | ||||
| mbrValue :: ReportOpts -> Journal -> MultiBalanceReport -> MultiBalanceReport | ||||
| mbrValue ReportOpts{..} Journal{..} (MultiBalanceReport (spans, rows, (coltotals, rowtotaltotal, rowavgtotal))) = | ||||
|   MultiBalanceReport ( | ||||
| @ -299,11 +299,11 @@ mbrValue ReportOpts{..} Journal{..} (MultiBalanceReport (spans, rows, (coltotals | ||||
|         -- & reversed for quick lookup of the latest price. | ||||
|         prices = reverse $ sortOn mpdate jmarketprices | ||||
|         d = case value_at_ of | ||||
|           AtTransaction -> error' "sorry, --value-at=transaction is not yet supported with multicolumn balance reports"  -- XXX | ||||
|           AtTransaction -> error' "sorry, --value-at=transaction is not yet supported with balance reports"  -- XXX | ||||
|           AtPeriod      -> periodend | ||||
|           AtNow         -> case today_ of | ||||
|                              Just d  -> d | ||||
|                              Nothing -> error' "ReportOpts today_ is unset so could not satisfy --value-at=now" | ||||
|                              Nothing -> error' "mbrValue: ReportOpts today_ is unset so could not satisfy --value-at=now" | ||||
|           AtDate d      -> d | ||||
| 
 | ||||
| -- | Generates a simple non-columnar BalanceReport, but using multiBalanceReport,  | ||||
|  | ||||
| @ -1,10 +1,16 @@ | ||||
| {-# LANGUAGE RecordWildCards, DeriveDataTypeable, FlexibleInstances, TupleSections, OverloadedStrings #-} | ||||
| {-| | ||||
| 
 | ||||
| Postings report, used by the register command. | ||||
| 
 | ||||
| -} | ||||
| 
 | ||||
| {-# LANGUAGE DeriveDataTypeable #-} | ||||
| {-# LANGUAGE FlexibleInstances #-} | ||||
| {-# LANGUAGE OverloadedStrings #-} | ||||
| {-# LANGUAGE RecordWildCards #-} | ||||
| {-# LANGUAGE ScopedTypeVariables #-} | ||||
| {-# LANGUAGE TupleSections #-} | ||||
| 
 | ||||
| module Hledger.Reports.PostingsReport ( | ||||
|   PostingsReport, | ||||
|   PostingsReportItem, | ||||
| @ -228,22 +234,44 @@ negatePostingAmount p = p { pamount = negate $ pamount p } | ||||
| -- | Convert all the posting amounts in a PostingsReport to their | ||||
| -- default valuation commodities. This means using the Journal's most | ||||
| -- recent applicable market prices before the valuation date. | ||||
| -- The valuation date is the specified report end date if any, | ||||
| -- otherwise the current date, otherwise the journal's end date. | ||||
| -- The valuation date is set with --value-at and can be: | ||||
| -- each posting's date, | ||||
| -- the last day in the report period (or in the journal if no period, | ||||
| -- or the posting dates if journal is empty - shouldn't happen), | ||||
| -- or today's date (gives an error if today_ is not set in ReportOpts), | ||||
| -- or a specified date. | ||||
| prValue :: ReportOpts -> Journal -> PostingsReport -> PostingsReport | ||||
| prValue ropts j r = | ||||
|   let mvaluationdate = periodEnd (period_ ropts) <|> today_ ropts <|> journalEndDate False j | ||||
|   in case mvaluationdate of | ||||
|     Nothing -> r | ||||
|     Just d  -> r' | ||||
| prValue ropts@ReportOpts{..} j@Journal{..} (totallabel, items) = (totallabel, items') | ||||
|   where | ||||
|     items' = [ (md, md2, desc, p{pamount=val $ pamount p}, val tot) | ||||
|              | (md, md2, desc, p, tot) <- items | ||||
|              , let val = mixedAmountValue prices (valuationdate $ postingDate p) | ||||
|              ] | ||||
|     valuationdate pdate = | ||||
|       case value_at_ of | ||||
|         AtTransaction | interval_ /= NoInterval -> error' "sorry, --value-at=transaction is not yet supported with periodic register reports"  -- XXX | ||||
|         AtPeriod      | interval_ /= NoInterval -> error' "sorry, --value-at=transaction is not yet supported with periodic register reports"  -- XXX | ||||
|         AtTransaction -> pdate | ||||
|         AtPeriod      -> fromMaybe pdate mperiodorjournallastday | ||||
|         AtNow         -> case today_ of | ||||
|                            Just d  -> d | ||||
|                            Nothing -> error' "prValue: ReportOpts today_ is unset so could not satisfy --value-at=now" | ||||
|         AtDate d      -> d | ||||
|       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 j | ||||
|         (label,items) = r | ||||
|         r' = (label, [(md,md2,desc,valueposting p, mixedAmountValue prices d amt) | (md,md2,desc,p,amt) <- items]) | ||||
|         valueposting p@Posting{..} = p{pamount=mixedAmountValue prices d pamount} | ||||
|         mperiodorjournallastday = mperiodlastday <|> journalEndDate False j | ||||
|         -- Get the last day of the report period. | ||||
|         -- Will be Nothing if no report period is specified, or also | ||||
|         -- if ReportOpts does not have today_ set, since we need that | ||||
|         -- to get the report period robustly. | ||||
|         mperiodlastday :: Maybe Day = do | ||||
|           t <- today_ | ||||
|           let q = queryFromOpts t ropts | ||||
|           qend <- queryEndDate False q | ||||
|           return $ addDays (-1) qend | ||||
| 
 | ||||
|     -- prices are in parse order - sort into date then parse order, | ||||
|     -- & reversed for quick lookup of the latest price. | ||||
|     prices = reverse $ sortOn mpdate jmarketprices | ||||
| 
 | ||||
| -- tests | ||||
| 
 | ||||
|  | ||||
| @ -94,6 +94,7 @@ data ReportOpts = ReportOpts { | ||||
|      today_          :: Maybe Day  -- ^ The current date. A late addition to ReportOpts. | ||||
|                                    -- Optional, but when set it may affect some reports: | ||||
|                                    -- Reports use it when picking a -V valuation date. | ||||
|                                    -- This is not great, adds indeterminacy. | ||||
|     ,period_         :: Period | ||||
|     ,interval_       :: Interval | ||||
|     ,statuses_       :: [Status]  -- ^ Zero, one, or two statuses to be matched | ||||
|  | ||||
| @ -502,10 +502,12 @@ The precise effect of the keywords is command-specific, but here is their genera | ||||
| 
 | ||||
| - `--value-at=transaction` (or `t`) | ||||
| : Use the prices as of each transaction date (more precisely, each [posting date](/journal.html#posting-dates)). | ||||
| : (Currently not supported with: balance commands, periodic register reports.) | ||||
| 
 | ||||
| - `--value-at=period` (or `p`) | ||||
| : Use the prices as of the last day of the report period (or each subperiod). | ||||
| : When no report period is specified, this will be the journal's last transaction date. | ||||
| : (Currently not supported with: periodic register reports.) | ||||
| 
 | ||||
| - `--value-at=now` (or `n`) | ||||
| : Use the prices as of today's date when the report is generated. This is the default. | ||||
| @ -514,11 +516,6 @@ The precise effect of the keywords is command-specific, but here is their genera | ||||
| : Use the prices as of the given date (8 digits with `-` or `/` or `.` separators). | ||||
| : Eg `--value-at=2019-04-25`. | ||||
| 
 | ||||
| Currently `--value-at` affects only some commands | ||||
| ([print](/hledger.html#print), | ||||
| [multicolumn balance reports](/hledger.html#balance)), | ||||
| and some of the keywords may not be supported by certain commands. | ||||
| 
 | ||||
| Here are some examples to show its effect: | ||||
| 
 | ||||
| ```journal | ||||
|  | ||||
| @ -28,8 +28,24 @@ $ hledger -f- bal -N -V | ||||
|              $135.00  expenses:foreign | ||||
| 
 | ||||
| 
 | ||||
| # 3. Market prices in the future (later than today's date) are always ignored. #453, #683 | ||||
| # XXX not working right now | ||||
| # 3. The location of price directives does not matter. | ||||
| # If multiple directives have the same date, the last parsed is used. | ||||
| < | ||||
| 3000/01/01 | ||||
|   (a)    $100 | ||||
| 
 | ||||
| P 2000/1/1 $ €1.35 | ||||
| 
 | ||||
| 3000/03/03 | ||||
|   (b)    $100 | ||||
| 
 | ||||
| P 2000/1/1 $ €1.30 | ||||
| 
 | ||||
| $ hledger -f- bal -N -V a | ||||
|              €130.00  a | ||||
| 
 | ||||
| 
 | ||||
| # 4. Market prices in the future (later than today's date) are ignored by default. #453, #683 | ||||
| < | ||||
| P 2000/1/1 $ €1.20 | ||||
| P 3000/1/1 $ €1.30 | ||||
| @ -41,37 +57,16 @@ $ hledger -f- bal -N -V | ||||
|              €120.00  a | ||||
| 
 | ||||
| 
 | ||||
| # 4. The market prices in effect at the report end date are used. | ||||
| # The location of price directives does not matter. | ||||
| # If multiple directives have the same date, the last parsed is used. | ||||
| < | ||||
| P 3000/3/1 $ €1.40 | ||||
| 
 | ||||
| 3000/01/01 | ||||
|   (a)    $100 | ||||
| 
 | ||||
| 3000/03/03 | ||||
|   (b)    $100 | ||||
| 
 | ||||
| P 2000/1/1 $ €1.20 | ||||
| P 3000/1/1 $ €1.35 | ||||
| P 3000/1/1 $ €1.30 | ||||
| 
 | ||||
| $ hledger -f- bal -N -V a -e 3000/2 | ||||
|              €130.00  a | ||||
| 
 | ||||
| 
 | ||||
| # 5. Again, this time there are prices later than the journal data and | ||||
| # an explicit report end date brings them into play. | ||||
| # 5. Market prices in the future are still ignored by default even | ||||
| # with an explicit future report end date, unlike hledger 1.14-. | ||||
| < | ||||
| P 3000/1/1 $ €1.10 | ||||
| P 3000/2/1 $ €1.30 | ||||
| 
 | ||||
| 3000/01/01 | ||||
|   (a)    $100 | ||||
| 
 | ||||
| $ hledger -f- bal -N -V a -e 3000/2 | ||||
|              €130.00  a | ||||
| $ hledger -f- bal -N -V -e 3000/2 | ||||
|                 $100  a | ||||
| 
 | ||||
| 
 | ||||
| # 6. Market prices interact with D directives and with amount style canonicalisation. #131 | ||||
| @ -210,7 +205,7 @@ Balance changes in 2000q1: | ||||
| 
 | ||||
| # 15. multicolumn balance report valued at transaction is not supported | ||||
| $ hledger -f- bal -M --value-at=transaction | ||||
| >2 /--value-at=transaction is not yet supported with multicolumn balance reports/ | ||||
| >2 /not yet supported with balance reports/ | ||||
| >=1 | ||||
|   | ||||
| # 16. multicolumn balance report valued at period end | ||||
| @ -243,3 +238,84 @@ Balance changes in 2000q1: | ||||
| ---++--------------- | ||||
|    || 1 B  1 B  1 B  | ||||
| 
 | ||||
| # 19. single column balance report with default value | ||||
| $ hledger -f- bal -V | ||||
|                 12 B  a | ||||
| -------------------- | ||||
|                 12 B | ||||
| 
 | ||||
| # 20. single column balance report valued at transaction is not supported | ||||
| $ hledger -f- bal --value-at=transaction | ||||
| >2 /not yet supported with balance reports/ | ||||
| >=1 | ||||
|   | ||||
| # 21. single column balance report valued at period end | ||||
| $ hledger -f- bal --value-at=period | ||||
|                  9 B  a | ||||
| -------------------- | ||||
|                  9 B | ||||
| 
 | ||||
| # 22. single column balance report valued at today | ||||
| $ hledger -f- bal --value-at=now | ||||
|                 12 B  a | ||||
| -------------------- | ||||
|                 12 B | ||||
| 
 | ||||
| # 23. single column balance report valued at other date | ||||
| $ hledger -f- bal --value-at=2000-01-15 | ||||
|                  3 B  a | ||||
| -------------------- | ||||
|                  3 B | ||||
| 
 | ||||
| # 24. register report with default value | ||||
| $ hledger -f- reg -V | ||||
| 2000/01/01                      (a)                            4 B           4 B | ||||
| 2000/02/01                      (a)                            4 B           8 B | ||||
| 2000/03/01                      (a)                            4 B          12 B | ||||
| 
 | ||||
| # 25. register report valued at transaction | ||||
| $ hledger -f- reg --value-at=transaction | ||||
| 2000/01/01                      (a)                            1 B           1 B | ||||
| 2000/02/01                      (a)                            2 B           4 B | ||||
| 2000/03/01                      (a)                            3 B           9 B | ||||
|   | ||||
| # 26. register report valued at period end | ||||
| $ hledger -f- reg --value-at=period | ||||
| 2000/01/01                      (a)                            3 B           3 B | ||||
| 2000/02/01                      (a)                            3 B           6 B | ||||
| 2000/03/01                      (a)                            3 B           9 B | ||||
| 
 | ||||
| # 27. register report valued at today | ||||
| $ hledger -f- reg --value-at=now | ||||
| 2000/01/01                      (a)                            4 B           4 B | ||||
| 2000/02/01                      (a)                            4 B           8 B | ||||
| 2000/03/01                      (a)                            4 B          12 B | ||||
| 
 | ||||
| # 28. register report valued at other date | ||||
| $ hledger -f- reg --value-at=2000-01-15 | ||||
| 2000/01/01                      (a)                            1 B           1 B | ||||
| 2000/02/01                      (a)                            1 B           2 B | ||||
| 2000/03/01                      (a)                            1 B           3 B | ||||
| 
 | ||||
| # 29. periodic register report with default value | ||||
| $ hledger -f- reg -V -Q | ||||
| 2000q1                  a                                     12 B          12 B | ||||
| 
 | ||||
| # 30. periodic register report valued at transaction | ||||
| $ hledger -f- reg --value-at=transaction -Q | ||||
| >2 /not yet supported with periodic register reports/ | ||||
| >=1 | ||||
|   | ||||
| # 31. periodic register report valued at period end | ||||
| $ hledger -f- reg --value-at=period -Q | ||||
| >2 /not yet supported with periodic register reports/ | ||||
| >=1 | ||||
| 
 | ||||
| # 32. periodic register report valued at today | ||||
| $ hledger -f- reg --value-at=now -Q | ||||
| 2000q1                  a                                     12 B          12 B | ||||
| 
 | ||||
| # 33. periodic register report valued at other date | ||||
| $ hledger -f- reg --value-at=2000-01-15 -Q | ||||
| 2000q1                  a                                      3 B           3 B | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user