imp: bal: budget goals now respect -H (#1879)
This commit is contained in:
parent
3e60e784f3
commit
42bcbad2fd
@ -76,7 +76,7 @@ module Hledger.Data.Dates (
|
||||
daysInSpan,
|
||||
|
||||
tests_Dates
|
||||
)
|
||||
, intervalStartBefore)
|
||||
where
|
||||
|
||||
import qualified Control.Monad.Fail as Fail (MonadFail, fail)
|
||||
@ -548,6 +548,13 @@ prevyear = startofyear . addGregorianYearsClip (-1)
|
||||
nextyear = startofyear . addGregorianYearsClip 1
|
||||
startofyear day = fromGregorian y 1 1 where (y,_,_) = toGregorian day
|
||||
|
||||
-- Get the natural start for the given interval that falls on or before the given day.
|
||||
intervalStartBefore :: Interval -> Day -> Day
|
||||
intervalStartBefore int d =
|
||||
case splitSpan int (DateSpan (Just d) (Just $ addDays 1 d)) of
|
||||
(DateSpan (Just start) _:_) -> start
|
||||
_ -> d
|
||||
|
||||
-- | For given date d find year-long interval that starts on given
|
||||
-- MM/DD of year and covers it.
|
||||
-- The given MM and DD should be basically valid (1-12 & 1-31),
|
||||
|
||||
@ -73,7 +73,9 @@ instance Show PeriodicTransaction where
|
||||
|
||||
--nullperiodictransaction is defined in Types.hs
|
||||
|
||||
-- | Generate transactions from 'PeriodicTransaction' within a 'DateSpan'
|
||||
-- | Generate transactions from 'PeriodicTransaction' within a 'DateSpan'.
|
||||
-- This should be a closed span with both start and end dates specified;
|
||||
-- an open ended span will generate no transactions.
|
||||
--
|
||||
-- Note that new transactions require 'txnTieKnot' post-processing.
|
||||
-- The new transactions will have three tags added:
|
||||
|
||||
@ -28,7 +28,7 @@ import Data.HashMap.Strict (HashMap)
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import Data.List (find, partition, transpose, foldl')
|
||||
import Data.List.Extra (nubSort)
|
||||
import Data.Maybe (fromMaybe, catMaybes)
|
||||
import Data.Maybe (fromMaybe, catMaybes, isJust)
|
||||
import Data.Map (Map)
|
||||
import qualified Data.Map as Map
|
||||
import qualified Data.Set as S
|
||||
@ -36,6 +36,7 @@ import Data.Text (Text)
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Builder as TB
|
||||
import Safe (maximumDef, minimumDef)
|
||||
--import System.Console.CmdArgs.Explicit as C
|
||||
--import Lucid as L
|
||||
import qualified Text.Tabular.AsciiWide as Tab
|
||||
@ -96,27 +97,47 @@ budgetReport rspec bopts reportspan j = dbg4 "sortedbudgetreport" budgetreport
|
||||
| otherwise = budgetgoalreport
|
||||
budgetreport = combineBudgetAndActual ropts j budgetgoalreport' actualreport
|
||||
|
||||
-- | Use all periodic transactions in the journal to generate
|
||||
-- budget goal transactions in the specified date span.
|
||||
-- Budget goal transactions are similar to forecast transactions except
|
||||
-- their purpose and effect is to define balance change goals, per account and period,
|
||||
-- for BudgetReport.
|
||||
-- | Use all (or all matched by --budget's argument) periodic transactions in the journal
|
||||
-- to generate budget goal transactions in the specified date span (and before, to support
|
||||
-- --historical. The precise start date is the natural start date of the largest interval
|
||||
-- of the active periodic transaction rules that is on or before the earlier of journal start date,
|
||||
-- report start date.)
|
||||
-- Budget goal transactions are similar to forecast transactions except their purpose
|
||||
-- and effect is to define balance change goals, per account and period, for BudgetReport.
|
||||
--
|
||||
journalAddBudgetGoalTransactions :: BalancingOpts -> ReportOpts -> DateSpan -> Journal -> Journal
|
||||
journalAddBudgetGoalTransactions bopts ropts reportspan j =
|
||||
either error' id $ journalBalanceTransactions bopts j{ jtxns = budgetts } -- PARTIAL:
|
||||
where
|
||||
budgetspan = dbg3 "budget span" $ reportspan
|
||||
pat = fromMaybe "" $ dbg3 "budget pattern" $ T.toLower <$> budgetpat_ ropts
|
||||
budgetspan = dbg3 "budget span" $ DateSpan mbudgetgoalsstartdate (spanEnd reportspan)
|
||||
where
|
||||
mbudgetgoalsstartdate =
|
||||
-- We want to also generate budget goal txns before the report start date, in case -H is used.
|
||||
-- What should the actual starting date for goal txns be ? This gets a little tricky: consider a
|
||||
-- journal with a "~ monthly" periodic transaction rule, where the first transaction is on 1/5.
|
||||
-- Users will certainly expect a budget goal for january, but "~ monthly" generates transactions
|
||||
-- on the first of month, and starting from 1/5 would exclude 1/1.
|
||||
-- Hopefully the following procedure will produce intuitive behaviour in general:
|
||||
-- from the earlier of the journal start date and the report start date,
|
||||
-- move backward to the nearest natural start date of the largest period seen among the
|
||||
-- active periodic transactions (so here: monthly, 1/5 -> 1/1).
|
||||
case minimumDef Nothing $ filter isJust [journalStartDate False j, spanStart reportspan] of
|
||||
Nothing -> Nothing
|
||||
Just d -> Just $ intervalStartBefore biggestinterval d
|
||||
where
|
||||
biggestinterval = maximumDef (Days 1) $ map ptinterval budgetpts
|
||||
|
||||
-- select periodic transactions matching a pattern
|
||||
-- (the argument of the (final) --budget option).
|
||||
-- XXX two limitations/wishes, requiring more extensive type changes:
|
||||
-- - give an error if pat is non-null and matches no periodic txns
|
||||
-- - allow a regexp or a full hledger query, not just a substring
|
||||
pat = fromMaybe "" $ dbg3 "budget pattern" $ T.toLower <$> budgetpat_ ropts
|
||||
budgetpts = [pt | pt <- jperiodictxns j, pat `T.isInfixOf` T.toLower (ptdescription pt)]
|
||||
budgetts =
|
||||
dbg5 "budget goal txns" $
|
||||
[makeBudgetTxn t
|
||||
| pt <- jperiodictxns j
|
||||
, pat `T.isInfixOf` T.toLower (ptdescription pt)
|
||||
| pt <- budgetpts
|
||||
, t <- runPeriodicTransaction pt budgetspan
|
||||
]
|
||||
makeBudgetTxn t = txnTieKnot $ t { tdescription = T.pack "Budget transaction" }
|
||||
|
||||
@ -635,3 +635,33 @@ $ hledger -f- bal --budget=weekly -p 2021-01
|
||||
$ hledger -f- bal --budget=monthly -p 2021-01
|
||||
> !/aaa/
|
||||
>=
|
||||
|
||||
# 33. Cumulative budget report.
|
||||
<
|
||||
~ monthly
|
||||
(a) 10
|
||||
|
||||
2022-01-05
|
||||
(a) 10
|
||||
|
||||
2022-02-03
|
||||
(a) 5
|
||||
|
||||
$ hledger -f- bal --budget -M --cumulative
|
||||
Budget performance in 2022-01-01..2022-02-28:
|
||||
|
||||
|| 2022-01-31 2022-02-28
|
||||
===++=================================
|
||||
a || 10 [100% of 10] 15 [75% of 20]
|
||||
---++---------------------------------
|
||||
|| 10 [100% of 10] 15 [75% of 20]
|
||||
|
||||
# 34. Historical budget report.
|
||||
$ hledger -f- bal --budget -M --historical -b 2022-02-01
|
||||
Budget performance in 2022-02:
|
||||
|
||||
|| 2022-02-28
|
||||
===++================
|
||||
a || 15 [75% of 20]
|
||||
---++----------------
|
||||
|| 15 [75% of 20]
|
||||
|
||||
Loading…
Reference in New Issue
Block a user