Skip to content

Commit

Permalink
opts: new -B/--cost, -V/--market, --value flags (#329)
Browse files Browse the repository at this point in the history
  • Loading branch information
simonmichael committed May 23, 2019
1 parent 0b67df2 commit f999bf7
Show file tree
Hide file tree
Showing 12 changed files with 170 additions and 150 deletions.
3 changes: 2 additions & 1 deletion hledger-lib/Hledger/Data/Journal.hs
Expand Up @@ -978,7 +978,8 @@ canonicalStyleFrom ss@(first:_) = first {asprecision = prec, asdecimalpoint = md
-- case ps of (MarketPrice{mpamount=a}:_) -> Just a
-- _ -> Nothing

-- | Convert all this journal's amounts to cost by applying their prices, if any.
-- | Convert all this journal's amounts to cost using the transaction prices, if any.
-- The journal's commodity styles are applied to the resulting amounts.
journalConvertAmountsToCost :: Journal -> Journal
journalConvertAmountsToCost j@Journal{jtxns=ts} = j{jtxns=map fixtransaction ts}
where
Expand Down
14 changes: 6 additions & 8 deletions hledger-lib/Hledger/Reports/BalanceReport.hs
Expand Up @@ -75,13 +75,11 @@ balanceReport ropts@ReportOpts{..} q j =
-- transaction: value each posting at posting date before summing
-- period: value totals at period end
-- date: value totals at date
mvalueat = valueTypeFromOpts ropts
today = fromMaybe (error' "balanceReport: ReportOpts today_ is unset so could not satisfy --value-at=now") today_

-- For --value-at=transaction, convert all postings to value before summing them.
-- The report might not use them all but laziness probably helps here.
j' | mvalueat==Just AtTransaction =
mapJournalPostings (\p -> postingValueAtDate j (postingDate p) p) j
j' -- | mvalueat==Just AtTransaction = mapJournalPostings (\p -> postingValueAtDate j (postingDate p) p) j
| otherwise = j

-- Get all the summed accounts & balances, according to the query, as an account tree.
Expand All @@ -92,11 +90,11 @@ balanceReport ropts@ReportOpts{..} q j =
where
valueaccount a@Account{..} = a{aebalance=val aebalance, aibalance=val aibalance}
where
val = case mvalueat of
Just AtPeriod -> mixedAmountValue prices periodlastday
Just AtNow -> mixedAmountValue prices today
Just (AtDate d) -> mixedAmountValue prices d
_ -> id
val = case value_ of
Just (AtEnd _mc) -> mixedAmountValue prices periodlastday
Just (AtNow _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.
Expand Down
12 changes: 6 additions & 6 deletions hledger-lib/Hledger/Reports/BudgetReport.hs
Expand Up @@ -275,12 +275,12 @@ budgetReportAsText ropts@ReportOpts{..} budgetr@(PeriodicReport ( _, rows, _)) =
where
title = printf "Budget performance in %s%s:"
(showDateSpan $ budgetReportSpan budgetr)
(case valueTypeFromOpts ropts of
Just AtTransaction -> ", valued at transaction dates"
Just AtPeriod -> ", valued at period ends"
Just AtNow -> ", current value"
Just (AtDate d) -> ", valued at "++showDate d
Nothing -> "")
(case value_ of
Just (AtCost _mc) -> ", valued at transaction dates"
Just (AtEnd _mc) -> ", valued at period ends"
Just (AtNow _mc) -> ", current value"
Just (AtDate d _mc) -> ", valued at "++showDate d
Nothing -> "")
actualwidth =
maximum [ maybe 0 (length . showMixedAmountOneLineWithoutPrice) amt
| (_, _, _, amtandgoals, _, _) <- rows
Expand Down
19 changes: 10 additions & 9 deletions hledger-lib/Hledger/Reports/EntriesReport.hs
Expand Up @@ -35,7 +35,7 @@ type EntriesReportItem = Transaction
-- | Select transactions for an entries report.
entriesReport :: ReportOpts -> Query -> Journal -> EntriesReport
entriesReport opts q j =
(if value_ opts then erValue opts j else id) $
(if isJust (value_ opts) then erValue opts j else id) $
sortBy (comparing date) $ filter (q `matchesTransaction`) ts
where
date = transactionDateFn opts
Expand Down Expand Up @@ -72,14 +72,15 @@ erValue ropts@ReportOpts{..} j ts = map txnvalue ts

mperiodorjournallastday = mperiodlastday <|> journalEndDate False j

d = case value_at_ of
AtTransaction -> postingDate p
AtPeriod -> fromMaybe (postingDate p) -- XXX shouldn't happen
mperiodorjournallastday
AtNow -> case today_ of
Just d -> d
Nothing -> error' "erValue: ReportOpts today_ is unset so could not satisfy --value-at=now"
AtDate d -> d
d = case value_ of
Just (AtCost _mc) -> postingDate p
Just (AtEnd _mc) -> fromMaybe (postingDate p) -- XXX shouldn't happen
mperiodorjournallastday
Just (AtNow _mc) -> case today_ of
Just d -> d
Nothing -> error' "erValue: ReportOpts today_ is unset so could not satisfy --value-at=now"
Just (AtDate d _mc) -> d
Nothing -> error' "erValue: shouldn't happen" -- XXX

tests_EntriesReport = tests "EntriesReport" [
tests "entriesReport" [
Expand Down
78 changes: 39 additions & 39 deletions hledger-lib/Hledger/Reports/MultiBalanceReports.hs
Expand Up @@ -157,19 +157,19 @@ multiBalanceReport ropts@ReportOpts{..} q j =
-- transaction: sum/average the valued amounts
-- period: sum/average the unvalued amounts and value at report period end
-- date: sum/average the unvalued amounts and value at date
mvalueat = valueTypeFromOpts ropts
-- mvalueat = valueTypeFromOpts ropts
today = fromMaybe (error' "postingsReport: ReportOpts today_ is unset so could not satisfy --value-at=now") today_
-- Market prices. Sort into date then parse order,
-- & reverse for quick lookup of the latest price.
prices = reverse $ sortOn mpdate $ jmarketprices j
-- A helper for valuing amounts according to --value-at.
maybevalue :: Day -> MixedAmount -> MixedAmount
maybevalue periodlastday amt = case mvalueat of
Nothing -> amt
Just AtTransaction -> amt -- assume --value-at=transaction was handled earlier
Just AtPeriod -> mixedAmountValue prices periodlastday amt
Just AtNow -> mixedAmountValue prices today amt
Just (AtDate d) -> mixedAmountValue prices d amt
maybevalue periodlastday amt = case value_ of
Nothing -> amt
Just (AtCost _mc) -> amt -- assume --value-at=transaction was handled earlier
Just (AtEnd _mc) -> mixedAmountValue prices periodlastday amt
Just (AtNow _mc) -> mixedAmountValue prices today amt
Just (AtDate d _mc) -> mixedAmountValue prices d amt
-- The last day of each column subperiod.
lastdays :: [Day] =
map ((maybe
Expand All @@ -187,7 +187,7 @@ multiBalanceReport ropts@ReportOpts{..} q j =
-- Balances at report start date, unvalued, from all earlier postings which otherwise match the query.
startbals :: [(AccountName, MixedAmount)] = dbg1 "startbals" $ map (\(a,_,_,b) -> (a,b)) startbalanceitems
where
(startbalanceitems,_) = dbg1 "starting balance report" $ balanceReport ropts''{value_=False} startbalq j
(startbalanceitems,_) = dbg1 "starting balance report" $ balanceReport ropts''{value_=Nothing} startbalq j
where
ropts' | tree_ ropts = ropts{no_elide_=True}
| otherwise = ropts{accountlistmode_=ALFlat}
Expand Down Expand Up @@ -243,9 +243,9 @@ multiBalanceReport ropts@ReportOpts{..} q j =
[(filter (isPostingInDateSpan' (whichDateFromOpts ropts) s) ps, spanEnd s) | s <- colspans]
-- If --value-at=transaction is in effect, convert the postings to value before summing.
colpsmaybevalued :: [([Posting], Maybe Day)] =
case mvalueat of
Just AtTransaction -> [([postingValueAtDate j (postingDate p) p | p <- ps], periodend) | (ps,periodend) <- colps]
_ -> colps
case value_ of
Just (AtCost _mc) -> [([postingValueAtDate j (postingDate p) p | p <- ps], periodend) | (ps,periodend) <- colps]
_ -> colps

----------------------------------------------------------------------
-- 5. Calculate account balance changes in each column.
Expand Down Expand Up @@ -325,25 +325,25 @@ multiBalanceReport ropts@ReportOpts{..} q j =
HistoricalBalance -> drop 1 $ scanl (+) (valuedStartingBalanceFor a) changes
CumulativeChange -> drop 1 $ scanl (+) 0 changes
_ -> changes
, let valuedbals = case mvalueat of
Just AtTransaction -> valuedbals1
Just AtPeriod -> [mixedAmountValue prices periodlastday amt | (amt,periodlastday) <- zip unvaluedbals lastdays]
Just AtNow -> [mixedAmountValue prices today amt | amt <- valuedbals1]
Just (AtDate d) -> [mixedAmountValue prices d amt | amt <- valuedbals1]
_ -> unvaluedbals --value-at=transaction was handled earlier
, let valuedbals = case value_ of
Just (AtCost _mc) -> valuedbals1
Just (AtEnd _mc) -> [mixedAmountValue prices periodlastday amt | (amt,periodlastday) <- zip unvaluedbals lastdays]
Just (AtNow _mc) -> [mixedAmountValue prices today amt | amt <- valuedbals1]
Just (AtDate d _mc) -> [mixedAmountValue prices d amt | amt <- valuedbals1]
_ -> unvaluedbals --value-at=transaction was handled earlier
-- The total and average for the row, and their values.
, let rowtot = if balancetype_==PeriodChange then sum unvaluedbals else 0
, let rowavg = averageMixedAmounts unvaluedbals
, let valuedrowtot = case mvalueat of
Just AtPeriod -> mixedAmountValue prices reportlastday rowtot
Just AtNow -> mixedAmountValue prices today rowtot
Just (AtDate d) -> mixedAmountValue prices d rowtot
_ -> rowtot
, let valuedrowavg = case mvalueat of
Just AtPeriod -> mixedAmountValue prices reportlastday rowavg
Just AtNow -> mixedAmountValue prices today rowavg
Just (AtDate d) -> mixedAmountValue prices d rowavg
_ -> rowavg
, let valuedrowtot = case value_ of
Just (AtEnd _mc) -> mixedAmountValue prices reportlastday rowtot
Just (AtNow _mc) -> mixedAmountValue prices today rowtot
Just (AtDate d _mc) -> mixedAmountValue prices d rowtot
_ -> rowtot
, let valuedrowavg = case value_ of
Just (AtEnd _mc) -> mixedAmountValue prices reportlastday rowavg
Just (AtNow _mc) -> mixedAmountValue prices today rowavg
Just (AtDate d _mc) -> mixedAmountValue prices d rowavg
_ -> rowavg
, empty_ || depth == 0 || any (not . isZeroMixedAmount) valuedbals
]

Expand Down Expand Up @@ -399,24 +399,24 @@ multiBalanceReport ropts@ReportOpts{..} q j =
colamtsvalued = transpose [bs | (a,_,_,bs,_,_) <- rowsvalued, not (tree_ ropts) || a `elem` highestlevelaccts]
coltotals :: [MixedAmount] =
dbg1 "coltotals" $
case mvalueat of
Nothing -> map sum colamts
Just AtTransaction -> map sum colamtsvalued
Just AtPeriod -> map (\(amts,periodlastday) -> maybevalue periodlastday $ sum amts) $ zip colamts lastdays
Just AtNow -> map (maybevalue today . sum) colamts
Just (AtDate d) -> map (maybevalue d . sum) colamts
case value_ of
Nothing -> map sum colamts
Just (AtCost _mc) -> map sum colamtsvalued
Just (AtEnd _mc) -> map (\(amts,periodlastday) -> maybevalue periodlastday $ sum amts) $ zip colamts lastdays
Just (AtNow _mc) -> map (maybevalue today . sum) colamts
Just (AtDate d _mc) -> map (maybevalue d . sum) colamts
-- Calculate and maybe value the grand total and average.
[grandtotal,grandaverage] =
let amts = map ($ map sum colamts)
[if balancetype_==PeriodChange then sum else const 0
,averageMixedAmounts
]
in case mvalueat of
Nothing -> amts
Just AtTransaction -> amts
Just AtPeriod -> map (maybevalue reportlastday) amts
Just AtNow -> map (maybevalue today) amts
Just (AtDate d) -> map (maybevalue d) amts
in case value_ of
Nothing -> amts
Just (AtCost _mc) -> amts
Just (AtEnd _mc) -> map (maybevalue reportlastday) amts
Just (AtNow _mc) -> map (maybevalue today) amts
Just (AtDate d _mc) -> map (maybevalue d) amts
-- Totals row.
totalsrow :: MultiBalanceReportTotals =
dbg1 "totalsrow" (coltotals, grandtotal, grandaverage)
Expand Down
33 changes: 16 additions & 17 deletions hledger-lib/Hledger/Reports/PostingsReport.hs
Expand Up @@ -87,7 +87,6 @@ postingsReport ropts@ReportOpts{..} q j =
--
-- "Day before report start" is a bit arbitrary.

mvalueat = valueTypeFromOpts ropts
today = fromMaybe (error' "postingsReport: ReportOpts today_ is unset so could not satisfy --value-at=now") today_

-- Postings or summary pseudo postings to be displayed.
Expand All @@ -100,29 +99,29 @@ postingsReport ropts@ReportOpts{..} q j =
showempty = empty_ || average_
-- for --value-at=transaction, need to value the postings before summarising them
maybevaluedreportps
| mvalueat==Just AtTransaction = [postingValueAtDate j (postingDate p) p | p <- reportps]
-- | value_==Just AtTransaction = [postingValueAtDate j (postingDate p) p | p <- reportps]
| otherwise = reportps
summaryps = summarisePostingsByInterval interval_ whichdate depth showempty reportspan maybevaluedreportps
in case mvalueat of
Just AtPeriod -> [(postingValueAtDate j periodlastday p , periodend) | (p,periodend) <- summaryps
in case value_ of
Just (AtEnd _mc) -> [(postingValueAtDate j 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 -> [(postingValueAtDate j today p , periodend) | (p,periodend) <- summaryps]
Just (AtDate d) -> [(postingValueAtDate j d p , periodend) | (p,periodend) <- summaryps]
Just (AtNow _mc) -> [(postingValueAtDate j today p , periodend) | (p,periodend) <- summaryps]
Just (AtDate d _mc) -> [(postingValueAtDate j d p , periodend) | (p,periodend) <- summaryps]
_ -> summaryps
else
let reportperiodlastday =
fromMaybe (error' "postingsReport: expected a non-empty journal") -- XXX shouldn't happen
$ reportPeriodOrJournalLastDay ropts j
in case mvalueat of
in case value_ of
Nothing -> [(p , Nothing) | p <- reportps]
Just AtTransaction -> [(postingValueAtDate j (postingDate p) p , Nothing) | p <- reportps]
Just AtPeriod -> [(postingValueAtDate j reportperiodlastday p, Nothing) | p <- reportps]
Just AtNow -> [(postingValueAtDate j today p , Nothing) | p <- reportps]
Just (AtDate d) -> [(postingValueAtDate j d p , Nothing) | p <- reportps]
Just (AtCost _mc) -> [(postingValueAtDate j (postingDate p) p , Nothing) | p <- reportps]
Just (AtEnd _mc) -> [(postingValueAtDate j reportperiodlastday p, Nothing) | p <- reportps]
Just (AtNow _mc) -> [(postingValueAtDate j today p , Nothing) | p <- reportps]
Just (AtDate d _mc) -> [(postingValueAtDate j d p , Nothing) | p <- reportps]

-- posting report items ready for display
items = dbg1 "postingsReport items" $ postingsReportItems displayps (nullposting,Nothing) whichdate depth valuedstartbal runningcalc startnum
Expand All @@ -137,12 +136,12 @@ postingsReport ropts@ReportOpts{..} q j =
-- For --value-at=transaction, we don't bother valuing each
-- preceding posting at posting date - how useful would that
-- be ? Just value the initial sum/average at report start date.
valuedstartbal = case mvalueat of
Nothing -> startbal
Just AtTransaction -> mixedAmountValue prices daybeforereportstart startbal
Just AtPeriod -> mixedAmountValue prices daybeforereportstart startbal
Just AtNow -> mixedAmountValue prices today startbal
Just (AtDate d) -> mixedAmountValue prices d startbal
valuedstartbal = case value_ of
Nothing -> startbal
Just (AtCost _mc) -> mixedAmountValue prices daybeforereportstart startbal
Just (AtEnd _mc) -> mixedAmountValue prices daybeforereportstart startbal
Just (AtNow _mc) -> mixedAmountValue prices today startbal
Just (AtDate d _mc) -> mixedAmountValue prices d startbal
where
daybeforereportstart = maybe
(error' "postingsReport: expected a non-empty journal") -- XXX shouldn't happen
Expand Down

0 comments on commit f999bf7

Please sign in to comment.