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