budget refactoring, type synonyms
Using "actual" and "budget" terminology. "real" is already used in the context of real/virtual postings. "actual" should be familiar from unit testing (expected & actual)..
This commit is contained in:
parent
a56c547bc2
commit
550425810f
@ -250,6 +250,7 @@ module Hledger.Cli.Commands.Balance (
|
||||
,tests_Hledger_Cli_Commands_Balance
|
||||
) where
|
||||
|
||||
import Data.Decimal
|
||||
import Data.List (intercalate, nub)
|
||||
import Data.Maybe
|
||||
import qualified Data.Map as Map
|
||||
@ -629,39 +630,53 @@ multiBalanceReportHtmlFootRow ropts (acct:rest) =
|
||||
-- | Render a multi-column balance report as plain text suitable for console output.
|
||||
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
|
||||
multiBalanceReportAsText opts r =
|
||||
printf "%s in %s:\n\n" typeStr (showDateSpan $ multiBalanceReportSpan r)
|
||||
printf "%s in %s:\n\n" desc (showDateSpan $ multiBalanceReportSpan r)
|
||||
++ renderBalanceReportTable opts tabl
|
||||
where
|
||||
tabl = balanceReportAsTable opts r
|
||||
typeStr :: String
|
||||
typeStr = case balancetype_ opts of
|
||||
desc = case balancetype_ opts of
|
||||
PeriodChange -> "Balance changes"
|
||||
CumulativeChange -> "Ending balances (cumulative)"
|
||||
HistoricalBalance -> "Ending balances (historical)"
|
||||
|
||||
type ActualAmount = MixedAmount
|
||||
type BudgetAmount = MixedAmount
|
||||
type ActualAmountsReport = MultiBalanceReport
|
||||
type BudgetAmountsReport = MultiBalanceReport
|
||||
type ActualAmountsTable = Table String String MixedAmount
|
||||
type BudgetAmountsTable = Table String String MixedAmount
|
||||
type ActualAndBudgetAmountsTable = Table String String (MixedAmount, Maybe MixedAmount)
|
||||
type Percentage = Decimal
|
||||
|
||||
-- | Given two multi-column balance reports, the first representing a budget
|
||||
-- (target change amounts) and the second representing actual change amounts,
|
||||
-- render a budget report as plain text suitable for console output.
|
||||
-- The reports should have the same number of columns.
|
||||
multiBalanceReportWithBudgetAsText :: ReportOpts -> MultiBalanceReport -> MultiBalanceReport -> String
|
||||
multiBalanceReportWithBudgetAsText opts budget r =
|
||||
printf "%s in %s:\n\n" typeStr (showDateSpan $ multiBalanceReportSpan r)
|
||||
++ renderBalanceReportTable' opts showcell tabl
|
||||
multiBalanceReportWithBudgetAsText :: ReportOpts -> BudgetAmountsReport -> ActualAmountsReport -> String
|
||||
multiBalanceReportWithBudgetAsText opts budgetr actualr =
|
||||
printf "%s in %s:\n\n" desc (showDateSpan $ multiBalanceReportSpan actualr)
|
||||
++ renderBalanceReportTable' opts showcell actualandbudgetamts
|
||||
where
|
||||
tabl = combine (balanceReportAsTable opts r) (balanceReportAsTable opts budget)
|
||||
typeStr :: String
|
||||
typeStr = case balancetype_ opts of
|
||||
desc :: String
|
||||
desc = case balancetype_ opts of
|
||||
PeriodChange -> "Balance changes"
|
||||
CumulativeChange -> "Ending balances (cumulative)"
|
||||
HistoricalBalance -> "Ending balances (historical)"
|
||||
showcell (real, Nothing) = showamt real
|
||||
showcell (real, Just budget) =
|
||||
case percentage real budget of
|
||||
Just pct -> printf "%s [%s%% of %s]" (showamt real) (show $ roundTo 0 pct) (showamt budget)
|
||||
Nothing -> printf "%s [%s]" (showamt real) (showamt budget)
|
||||
percentage real budget =
|
||||
|
||||
actualandbudgetamts :: ActualAndBudgetAmountsTable
|
||||
actualandbudgetamts = combine (balanceReportAsTable opts actualr) (balanceReportAsTable opts budgetr)
|
||||
|
||||
showcell :: (ActualAmount, Maybe BudgetAmount) -> String
|
||||
showcell (actual, Nothing) = showamt actual
|
||||
showcell (actual, Just budget) =
|
||||
case percentage actual budget of
|
||||
Just pct -> printf "%s [%s%% of %s]" (showamt actual) (show $ roundTo 0 pct) (showamt budget)
|
||||
Nothing -> printf "%s [%s]" (showamt actual) (showamt budget)
|
||||
|
||||
percentage :: ActualAmount -> BudgetAmount -> Maybe Percentage
|
||||
percentage actual budget =
|
||||
-- percentage of budget consumed is always computed in the cost basis
|
||||
case (toCost real, toCost budget) of
|
||||
case (toCost actual, toCost budget) of
|
||||
(Mixed [a1], Mixed [a2])
|
||||
| isReallyZeroAmount a1 -> Just 0 -- if there are no postings, we consumed 0% of budget
|
||||
| acommodity a1 == acommodity a2 && aquantity a2 /= 0 ->
|
||||
@ -669,6 +684,8 @@ multiBalanceReportWithBudgetAsText opts budget r =
|
||||
_ -> Nothing
|
||||
where
|
||||
toCost = normaliseMixedAmount . costOfMixedAmount
|
||||
|
||||
showamt :: MixedAmount -> String
|
||||
showamt | color_ opts = cshowMixedAmountOneLineWithoutPrice
|
||||
| otherwise = showMixedAmountOneLineWithoutPrice
|
||||
|
||||
@ -677,9 +694,10 @@ multiBalanceReportWithBudgetAsText opts budget r =
|
||||
-- The budget table's row/column titles should be a subset of the actual table's.
|
||||
-- (This is satisfied by the construction of the budget report and the
|
||||
-- process of rolling up account names.)
|
||||
combine :: ActualAmountsTable -> BudgetAmountsTable -> ActualAndBudgetAmountsTable
|
||||
combine (Table l t d) (Table l' t' d') = Table l t combinedRows
|
||||
where
|
||||
-- For all accounts that are present in the budget, zip real amounts with budget amounts
|
||||
-- For all accounts that are present in the budget, zip actual amounts with budget amounts
|
||||
combinedRows = [ combineRow row budgetRow
|
||||
| (acct, row) <- zip (headerContents l) d
|
||||
, let budgetRow =
|
||||
|
||||
Loading…
Reference in New Issue
Block a user