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
|
,tests_Hledger_Cli_Commands_Balance
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Data.Decimal
|
||||||
import Data.List (intercalate, nub)
|
import Data.List (intercalate, nub)
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import qualified Data.Map as Map
|
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.
|
-- | Render a multi-column balance report as plain text suitable for console output.
|
||||||
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
|
multiBalanceReportAsText :: ReportOpts -> MultiBalanceReport -> String
|
||||||
multiBalanceReportAsText opts r =
|
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
|
++ renderBalanceReportTable opts tabl
|
||||||
where
|
where
|
||||||
tabl = balanceReportAsTable opts r
|
tabl = balanceReportAsTable opts r
|
||||||
typeStr :: String
|
desc = case balancetype_ opts of
|
||||||
typeStr = case balancetype_ opts of
|
|
||||||
PeriodChange -> "Balance changes"
|
PeriodChange -> "Balance changes"
|
||||||
CumulativeChange -> "Ending balances (cumulative)"
|
CumulativeChange -> "Ending balances (cumulative)"
|
||||||
HistoricalBalance -> "Ending balances (historical)"
|
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
|
-- | Given two multi-column balance reports, the first representing a budget
|
||||||
-- (target change amounts) and the second representing actual change amounts,
|
-- (target change amounts) and the second representing actual change amounts,
|
||||||
-- render a budget report as plain text suitable for console output.
|
-- render a budget report as plain text suitable for console output.
|
||||||
-- The reports should have the same number of columns.
|
-- The reports should have the same number of columns.
|
||||||
multiBalanceReportWithBudgetAsText :: ReportOpts -> MultiBalanceReport -> MultiBalanceReport -> String
|
multiBalanceReportWithBudgetAsText :: ReportOpts -> BudgetAmountsReport -> ActualAmountsReport -> String
|
||||||
multiBalanceReportWithBudgetAsText opts budget r =
|
multiBalanceReportWithBudgetAsText opts budgetr actualr =
|
||||||
printf "%s in %s:\n\n" typeStr (showDateSpan $ multiBalanceReportSpan r)
|
printf "%s in %s:\n\n" desc (showDateSpan $ multiBalanceReportSpan actualr)
|
||||||
++ renderBalanceReportTable' opts showcell tabl
|
++ renderBalanceReportTable' opts showcell actualandbudgetamts
|
||||||
where
|
where
|
||||||
tabl = combine (balanceReportAsTable opts r) (balanceReportAsTable opts budget)
|
desc :: String
|
||||||
typeStr :: String
|
desc = case balancetype_ opts of
|
||||||
typeStr = case balancetype_ opts of
|
|
||||||
PeriodChange -> "Balance changes"
|
PeriodChange -> "Balance changes"
|
||||||
CumulativeChange -> "Ending balances (cumulative)"
|
CumulativeChange -> "Ending balances (cumulative)"
|
||||||
HistoricalBalance -> "Ending balances (historical)"
|
HistoricalBalance -> "Ending balances (historical)"
|
||||||
showcell (real, Nothing) = showamt real
|
|
||||||
showcell (real, Just budget) =
|
actualandbudgetamts :: ActualAndBudgetAmountsTable
|
||||||
case percentage real budget of
|
actualandbudgetamts = combine (balanceReportAsTable opts actualr) (balanceReportAsTable opts budgetr)
|
||||||
Just pct -> printf "%s [%s%% of %s]" (showamt real) (show $ roundTo 0 pct) (showamt budget)
|
|
||||||
Nothing -> printf "%s [%s]" (showamt real) (showamt budget)
|
showcell :: (ActualAmount, Maybe BudgetAmount) -> String
|
||||||
percentage real budget =
|
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
|
-- 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])
|
(Mixed [a1], Mixed [a2])
|
||||||
| isReallyZeroAmount a1 -> Just 0 -- if there are no postings, we consumed 0% of budget
|
| isReallyZeroAmount a1 -> Just 0 -- if there are no postings, we consumed 0% of budget
|
||||||
| acommodity a1 == acommodity a2 && aquantity a2 /= 0 ->
|
| acommodity a1 == acommodity a2 && aquantity a2 /= 0 ->
|
||||||
@ -669,6 +684,8 @@ multiBalanceReportWithBudgetAsText opts budget r =
|
|||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
where
|
where
|
||||||
toCost = normaliseMixedAmount . costOfMixedAmount
|
toCost = normaliseMixedAmount . costOfMixedAmount
|
||||||
|
|
||||||
|
showamt :: MixedAmount -> String
|
||||||
showamt | color_ opts = cshowMixedAmountOneLineWithoutPrice
|
showamt | color_ opts = cshowMixedAmountOneLineWithoutPrice
|
||||||
| otherwise = showMixedAmountOneLineWithoutPrice
|
| 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.
|
-- 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
|
-- (This is satisfied by the construction of the budget report and the
|
||||||
-- process of rolling up account names.)
|
-- process of rolling up account names.)
|
||||||
|
combine :: ActualAmountsTable -> BudgetAmountsTable -> ActualAndBudgetAmountsTable
|
||||||
combine (Table l t d) (Table l' t' d') = Table l t combinedRows
|
combine (Table l t d) (Table l' t' d') = Table l t combinedRows
|
||||||
where
|
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
|
combinedRows = [ combineRow row budgetRow
|
||||||
| (acct, row) <- zip (headerContents l) d
|
| (acct, row) <- zip (headerContents l) d
|
||||||
, let budgetRow =
|
, let budgetRow =
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user