imp!: forecast: Implements more intuitive logic for the forecast interval. (#1648)
The forecast period begins on: - the start date supplied to the `--forecast` argument, if present - otherwise, the later of - the report start date if specified with -b/-p/date: - the day after the latest normal (non-periodic) transaction in the journal, if any - otherwise today. It ends on: - the end date supplied to the `--forecast` argument, if present - otherwise the report end date if specified with -e/-p/date: - otherwise 180 days (6 months) from today. Note that the previous behaviour did not quite match the documentation, so this also acts as a bug fix for #1665.
This commit is contained in:
parent
65e10aebd2
commit
c07ad29a87
@ -36,6 +36,7 @@ module Hledger.Read (
|
|||||||
findReader,
|
findReader,
|
||||||
splitReaderPrefix,
|
splitReaderPrefix,
|
||||||
module Hledger.Read.Common,
|
module Hledger.Read.Common,
|
||||||
|
module Hledger.Read.InputOptions,
|
||||||
|
|
||||||
-- * Tests
|
-- * Tests
|
||||||
tests_Read,
|
tests_Read,
|
||||||
@ -69,6 +70,7 @@ import System.IO (hPutStr, stderr)
|
|||||||
import Hledger.Data.Dates (getCurrentDay, parsedateM, showDate)
|
import Hledger.Data.Dates (getCurrentDay, parsedateM, showDate)
|
||||||
import Hledger.Data.Types
|
import Hledger.Data.Types
|
||||||
import Hledger.Read.Common
|
import Hledger.Read.Common
|
||||||
|
import Hledger.Read.InputOptions
|
||||||
import Hledger.Read.JournalReader as JournalReader
|
import Hledger.Read.JournalReader as JournalReader
|
||||||
import Hledger.Read.CsvReader (tests_CsvReader)
|
import Hledger.Read.CsvReader (tests_CsvReader)
|
||||||
-- import Hledger.Read.TimedotReader (tests_TimedotReader)
|
-- import Hledger.Read.TimedotReader (tests_TimedotReader)
|
||||||
|
|||||||
@ -32,7 +32,6 @@ module Hledger.Read.Common (
|
|||||||
InputOpts(..),
|
InputOpts(..),
|
||||||
definputopts,
|
definputopts,
|
||||||
rawOptsToInputOpts,
|
rawOptsToInputOpts,
|
||||||
forecastPeriodFromRawOpts,
|
|
||||||
rawOptsToCommodityStylesOpts,
|
rawOptsToCommodityStylesOpts,
|
||||||
|
|
||||||
-- * parsing utilities
|
-- * parsing utilities
|
||||||
@ -148,7 +147,7 @@ import qualified Data.Map as M
|
|||||||
import qualified Data.Semigroup as Sem
|
import qualified Data.Semigroup as Sem
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Data.Time.Calendar (Day, addDays, fromGregorianValid, toGregorian)
|
import Data.Time.Calendar (Day, fromGregorianValid, toGregorian)
|
||||||
import Data.Time.Clock.POSIX (getPOSIXTime)
|
import Data.Time.Clock.POSIX (getPOSIXTime)
|
||||||
import Data.Time.LocalTime (LocalTime(..), TimeOfDay(..))
|
import Data.Time.LocalTime (LocalTime(..), TimeOfDay(..))
|
||||||
import Data.Word (Word8)
|
import Data.Word (Word8)
|
||||||
@ -160,7 +159,7 @@ import Text.Megaparsec.Custom
|
|||||||
finalErrorBundlePretty, parseErrorAt, parseErrorAtRegion)
|
finalErrorBundlePretty, parseErrorAt, parseErrorAtRegion)
|
||||||
|
|
||||||
import Hledger.Data
|
import Hledger.Data
|
||||||
import Hledger.Query (Query(..), filterQuery, parseQueryTerm, queryEndDate, queryIsDate, simplifyQuery)
|
import Hledger.Query (Query(..), filterQuery, parseQueryTerm, queryEndDate, queryStartDate, queryIsDate, simplifyQuery)
|
||||||
import Hledger.Reports.ReportOptions (ReportOpts(..), queryFromFlags, rawOptsToReportOpts)
|
import Hledger.Reports.ReportOptions (ReportOpts(..), queryFromFlags, rawOptsToReportOpts)
|
||||||
import Hledger.Utils
|
import Hledger.Utils
|
||||||
import Text.Printf (printf)
|
import Text.Printf (printf)
|
||||||
@ -234,6 +233,14 @@ rawOptsToInputOpts :: RawOpts -> IO InputOpts
|
|||||||
rawOptsToInputOpts rawopts = do
|
rawOptsToInputOpts rawopts = do
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
|
|
||||||
|
let noinferprice = boolopt "strict" rawopts || stringopt "args" rawopts == "balancednoautoconversion"
|
||||||
|
|
||||||
|
-- Do we really need to do all this work just to get the requested end date? This is duplicating
|
||||||
|
-- much of reportOptsToSpec.
|
||||||
|
ropts = rawOptsToReportOpts d rawopts
|
||||||
|
argsquery = lefts . rights . map (parseQueryTerm d) $ querystring_ ropts
|
||||||
|
datequery = simplifyQuery . filterQuery queryIsDate . And $ queryFromFlags ropts : argsquery
|
||||||
|
|
||||||
return InputOpts{
|
return InputOpts{
|
||||||
-- files_ = listofstringopt "file" rawopts
|
-- files_ = listofstringopt "file" rawopts
|
||||||
mformat_ = Nothing
|
mformat_ = Nothing
|
||||||
@ -244,6 +251,7 @@ rawOptsToInputOpts rawopts = do
|
|||||||
,new_save_ = True
|
,new_save_ = True
|
||||||
,pivot_ = stringopt "pivot" rawopts
|
,pivot_ = stringopt "pivot" rawopts
|
||||||
,forecast_ = forecastPeriodFromRawOpts d rawopts
|
,forecast_ = forecastPeriodFromRawOpts d rawopts
|
||||||
|
,reportspan_ = DateSpan (queryStartDate False datequery) (queryEndDate False datequery)
|
||||||
,auto_ = boolopt "auto" rawopts
|
,auto_ = boolopt "auto" rawopts
|
||||||
,balancingopts_ = balancingOpts{
|
,balancingopts_ = balancingOpts{
|
||||||
ignore_assertions_ = boolopt "ignore-assertions" rawopts
|
ignore_assertions_ = boolopt "ignore-assertions" rawopts
|
||||||
@ -252,36 +260,21 @@ rawOptsToInputOpts rawopts = do
|
|||||||
}
|
}
|
||||||
,strict_ = boolopt "strict" rawopts
|
,strict_ = boolopt "strict" rawopts
|
||||||
}
|
}
|
||||||
where noinferprice = boolopt "strict" rawopts || stringopt "args" rawopts == "balancednoautoconversion"
|
|
||||||
|
|
||||||
-- | Get the date span from --forecast's PERIODEXPR argument, if any.
|
-- | Get the date span from --forecast's PERIODEXPR argument, if any.
|
||||||
-- This will fail with a usage error if the period expression cannot be parsed,
|
-- This will fail with a usage error if the period expression cannot be parsed,
|
||||||
-- or if it contains a report interval.
|
-- or if it contains a report interval.
|
||||||
forecastPeriodFromRawOpts :: Day -> RawOpts -> Maybe DateSpan
|
forecastPeriodFromRawOpts :: Day -> RawOpts -> Maybe DateSpan
|
||||||
forecastPeriodFromRawOpts d rawopts = case maybestringopt "forecast" rawopts of
|
forecastPeriodFromRawOpts d rawopts = do
|
||||||
Nothing -> Nothing
|
arg <- maybestringopt "forecast" rawopts
|
||||||
Just "" -> Just forecastspanDefault
|
let period = parsePeriodExpr d . stripquotes $ T.pack arg
|
||||||
Just arg ->
|
return $ if null arg then nulldatespan else either badParse (getSpan arg) period
|
||||||
either
|
|
||||||
(\e -> usageError $ "could not parse forecast period : "++customErrorBundlePretty e)
|
|
||||||
(\(interval, requestedspan) ->
|
|
||||||
case interval of
|
|
||||||
NoInterval -> Just $ requestedspan `spanDefaultsFrom` forecastspanDefault
|
|
||||||
_ -> usageError $ unlines
|
|
||||||
[ "--forecast's argument should not contain a report interval"
|
|
||||||
, "(" ++ show interval ++ " in \"" ++ arg ++ "\")"
|
|
||||||
])
|
|
||||||
(parsePeriodExpr d $ stripquotes $ T.pack arg)
|
|
||||||
where
|
where
|
||||||
-- "They end on or before the specified report end date, or 180 days from today if unspecified."
|
badParse e = usageError $ "could not parse forecast period : "++customErrorBundlePretty e
|
||||||
mspecifiedend = dbg2 "specifieddates" $ queryEndDate False datequery
|
getSpan arg (interval, requestedspan) = case interval of
|
||||||
forecastendDefault = dbg2 "forecastendDefault" $ addDays 180 d
|
NoInterval -> requestedspan
|
||||||
forecastspanDefault = DateSpan Nothing $ mspecifiedend <|> Just forecastendDefault
|
_ -> usageError $ "--forecast's argument should not contain a report interval ("
|
||||||
-- Do we really need to do all this work just to get the requested end date? This is duplicating
|
++ show interval ++ " in \"" ++ arg ++ "\")"
|
||||||
-- much of reportOptsToSpec.
|
|
||||||
ropts = rawOptsToReportOpts d rawopts
|
|
||||||
argsquery = lefts . rights . map (parseQueryTerm d) $ querystring_ ropts
|
|
||||||
datequery = simplifyQuery . filterQuery queryIsDate . And $ queryFromFlags ropts : argsquery
|
|
||||||
|
|
||||||
--- ** parsing utilities
|
--- ** parsing utilities
|
||||||
|
|
||||||
@ -371,7 +364,7 @@ parseAndFinaliseJournal' parser iopts f txt = do
|
|||||||
-- - infer transaction-implied market prices from transaction prices
|
-- - infer transaction-implied market prices from transaction prices
|
||||||
--
|
--
|
||||||
journalFinalise :: InputOpts -> FilePath -> Text -> ParsedJournal -> ExceptT String IO Journal
|
journalFinalise :: InputOpts -> FilePath -> Text -> ParsedJournal -> ExceptT String IO Journal
|
||||||
journalFinalise InputOpts{forecast_,auto_,balancingopts_,strict_} f txt pj = do
|
journalFinalise iopts@InputOpts{auto_,balancingopts_,strict_} f txt pj = do
|
||||||
t <- liftIO getPOSIXTime
|
t <- liftIO getPOSIXTime
|
||||||
d <- liftIO getCurrentDay
|
d <- liftIO getCurrentDay
|
||||||
-- Infer and apply canonical styles for each commodity (or throw an error).
|
-- Infer and apply canonical styles for each commodity (or throw an error).
|
||||||
@ -390,7 +383,7 @@ journalFinalise InputOpts{forecast_,auto_,balancingopts_,strict_} f txt pj = do
|
|||||||
journalCheckCommoditiesDeclared j
|
journalCheckCommoditiesDeclared j
|
||||||
|
|
||||||
-- Add forecast transactions if enabled
|
-- Add forecast transactions if enabled
|
||||||
journalAddForecast d forecast_ j
|
journalAddForecast (forecastPeriod d iopts j) j
|
||||||
-- Add auto postings if enabled
|
-- Add auto postings if enabled
|
||||||
& (if auto_ && not (null $ jtxnmodifiers j) then journalAddAutoPostings d balancingopts_ else pure)
|
& (if auto_ && not (null $ jtxnmodifiers j) then journalAddAutoPostings d balancingopts_ else pure)
|
||||||
-- Balance all transactions and maybe check balance assertions.
|
-- Balance all transactions and maybe check balance assertions.
|
||||||
@ -412,9 +405,9 @@ journalAddAutoPostings d bopts =
|
|||||||
--
|
--
|
||||||
-- The start & end date for generated periodic transactions are determined in
|
-- The start & end date for generated periodic transactions are determined in
|
||||||
-- a somewhat complicated way; see the hledger manual -> Periodic transactions.
|
-- a somewhat complicated way; see the hledger manual -> Periodic transactions.
|
||||||
journalAddForecast :: Day -> Maybe DateSpan -> Journal -> Journal
|
journalAddForecast :: Maybe DateSpan -> Journal -> Journal
|
||||||
journalAddForecast _ Nothing j = j
|
journalAddForecast Nothing j = j
|
||||||
journalAddForecast d (Just requestedspan) j = j{jtxns = jtxns j ++ forecasttxns}
|
journalAddForecast (Just forecastspan) j = j{jtxns = jtxns j ++ forecasttxns}
|
||||||
where
|
where
|
||||||
forecasttxns =
|
forecasttxns =
|
||||||
map (txnTieKnot . transactionTransformPostings (postingApplyCommodityStyles $ journalCommodityStyles j))
|
map (txnTieKnot . transactionTransformPostings (postingApplyCommodityStyles $ journalCommodityStyles j))
|
||||||
@ -422,14 +415,6 @@ journalAddForecast d (Just requestedspan) j = j{jtxns = jtxns j ++ forecasttxns}
|
|||||||
. concatMap (`runPeriodicTransaction` forecastspan)
|
. concatMap (`runPeriodicTransaction` forecastspan)
|
||||||
$ jperiodictxns j
|
$ jperiodictxns j
|
||||||
|
|
||||||
-- "They can start no earlier than: the day following the latest normal transaction in the journal (or today if there are none)."
|
|
||||||
mjournalend = dbg2 "journalEndDate" $ journalEndDate False j -- ignore secondary dates
|
|
||||||
forecastbeginDefault = dbg2 "forecastbeginDefault" $ mjournalend <|> Just d
|
|
||||||
|
|
||||||
-- "They end on or before the specified report end date, or 180 days from today if unspecified."
|
|
||||||
forecastspan = dbg2 "forecastspan" $ dbg2 "forecastspan flag" requestedspan
|
|
||||||
`spanDefaultsFrom` DateSpan forecastbeginDefault (Just $ addDays 180 d)
|
|
||||||
|
|
||||||
-- | Check that all the journal's transactions have payees declared with
|
-- | Check that all the journal's transactions have payees declared with
|
||||||
-- payee directives, returning an error message otherwise.
|
-- payee directives, returning an error message otherwise.
|
||||||
journalCheckPayeesDeclared :: Journal -> Either String ()
|
journalCheckPayeesDeclared :: Journal -> Either String ()
|
||||||
|
|||||||
@ -9,12 +9,17 @@ module Hledger.Read.InputOptions (
|
|||||||
-- * Types and helpers for input options
|
-- * Types and helpers for input options
|
||||||
InputOpts(..)
|
InputOpts(..)
|
||||||
, definputopts
|
, definputopts
|
||||||
)
|
, forecastPeriod
|
||||||
where
|
) where
|
||||||
|
|
||||||
|
import Control.Applicative ((<|>))
|
||||||
|
import Data.Time (Day, addDays)
|
||||||
|
|
||||||
import Hledger.Data.Types
|
import Hledger.Data.Types
|
||||||
import Hledger.Data.Transaction
|
import Hledger.Data.Transaction (BalancingOpts(..), balancingOpts)
|
||||||
import Hledger.Data.Dates()
|
import Hledger.Data.Journal (journalEndDate)
|
||||||
|
import Hledger.Data.Dates (nulldatespan)
|
||||||
|
import Hledger.Utils
|
||||||
|
|
||||||
data InputOpts = InputOpts {
|
data InputOpts = InputOpts {
|
||||||
-- files_ :: [FilePath]
|
-- files_ :: [FilePath]
|
||||||
@ -27,6 +32,7 @@ data InputOpts = InputOpts {
|
|||||||
,new_save_ :: Bool -- ^ save latest new transactions state for next time
|
,new_save_ :: Bool -- ^ save latest new transactions state for next time
|
||||||
,pivot_ :: String -- ^ use the given field's value as the account name
|
,pivot_ :: String -- ^ use the given field's value as the account name
|
||||||
,forecast_ :: Maybe DateSpan -- ^ span in which to generate forecast transactions
|
,forecast_ :: Maybe DateSpan -- ^ span in which to generate forecast transactions
|
||||||
|
,reportspan_ :: DateSpan -- ^ a dirty hack keeping the query dates in InputOpts. This rightfully lives in ReportSpec, but is duplicated here.
|
||||||
,auto_ :: Bool -- ^ generate automatic postings when journal is parsed
|
,auto_ :: Bool -- ^ generate automatic postings when journal is parsed
|
||||||
,balancingopts_ :: BalancingOpts -- ^ options for balancing transactions
|
,balancingopts_ :: BalancingOpts -- ^ options for balancing transactions
|
||||||
,strict_ :: Bool -- ^ do extra error checking (eg, all posted accounts are declared, no prices are inferred)
|
,strict_ :: Bool -- ^ do extra error checking (eg, all posted accounts are declared, no prices are inferred)
|
||||||
@ -42,7 +48,28 @@ definputopts = InputOpts
|
|||||||
, new_save_ = True
|
, new_save_ = True
|
||||||
, pivot_ = ""
|
, pivot_ = ""
|
||||||
, forecast_ = Nothing
|
, forecast_ = Nothing
|
||||||
|
, reportspan_ = nulldatespan
|
||||||
, auto_ = False
|
, auto_ = False
|
||||||
, balancingopts_ = balancingOpts
|
, balancingopts_ = balancingOpts
|
||||||
, strict_ = False
|
, strict_ = False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Get the Maybe the DateSpan to generate forecast options from.
|
||||||
|
-- This begins on:
|
||||||
|
-- - the start date supplied to the `--forecast` argument, if present
|
||||||
|
-- - otherwise, the later of
|
||||||
|
-- - the report start date if specified with -b/-p/date:
|
||||||
|
-- - the day after the latest normal (non-periodic) transaction in the journal, if any
|
||||||
|
-- - otherwise today.
|
||||||
|
-- It ends on:
|
||||||
|
-- - the end date supplied to the `--forecast` argument, if present
|
||||||
|
-- - otherwise the report end date if specified with -e/-p/date:
|
||||||
|
-- - otherwise 180 days (6 months) from today.
|
||||||
|
forecastPeriod :: Day -> InputOpts -> Journal -> Maybe DateSpan
|
||||||
|
forecastPeriod d iopts j = do
|
||||||
|
DateSpan requestedStart requestedEnd <- forecast_ iopts
|
||||||
|
let forecastStart = requestedStart <|> max mjournalend reportStart <|> Just d
|
||||||
|
forecastEnd = requestedEnd <|> reportEnd <|> Just (addDays 180 d)
|
||||||
|
mjournalend = dbg2 "journalEndDate" $ journalEndDate False j -- ignore secondary dates
|
||||||
|
DateSpan reportStart reportEnd = reportspan_ iopts
|
||||||
|
return . dbg2 "forecastspan" $ DateSpan forecastStart forecastEnd
|
||||||
|
|||||||
@ -7,7 +7,6 @@ module Hledger.UI.UIState
|
|||||||
where
|
where
|
||||||
|
|
||||||
import Brick.Widgets.Edit
|
import Brick.Widgets.Edit
|
||||||
import Control.Applicative ((<|>))
|
|
||||||
import Data.List ((\\), foldl', sort)
|
import Data.List ((\\), foldl', sort)
|
||||||
import Data.Semigroup (Max(..))
|
import Data.Semigroup (Max(..))
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@ -157,11 +156,11 @@ toggleHistorical ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec
|
|||||||
-- (which are usually but not necessarily future-dated).
|
-- (which are usually but not necessarily future-dated).
|
||||||
-- In normal mode, both of these are hidden.
|
-- In normal mode, both of these are hidden.
|
||||||
toggleForecast :: Day -> UIState -> UIState
|
toggleForecast :: Day -> UIState -> UIState
|
||||||
toggleForecast d ui@UIState{aopts=UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts}}} =
|
toggleForecast d ui@UIState{aopts=UIOpts{cliopts_=CliOpts{inputopts_=iopts}}} =
|
||||||
uiSetForecast ui $
|
uiSetForecast ui $
|
||||||
case forecast_ iopts of
|
case forecast_ iopts of
|
||||||
Just _ -> Nothing
|
Just _ -> Nothing
|
||||||
Nothing -> forecastPeriodFromRawOpts d (rawopts_ copts) <|> Just nulldatespan
|
Nothing -> forecastPeriod d iopts{forecast_=Just nulldatespan} (ajournal ui)
|
||||||
|
|
||||||
-- | Helper: set forecast mode (with the given forecast period) on or off in the UI state.
|
-- | Helper: set forecast mode (with the given forecast period) on or off in the UI state.
|
||||||
uiSetForecast :: UIState -> Maybe DateSpan -> UIState
|
uiSetForecast :: UIState -> Maybe DateSpan -> UIState
|
||||||
|
|||||||
@ -3165,15 +3165,16 @@ transactions generated "just now":
|
|||||||
`_generated-transaction:~ PERIODICEXPR`.
|
`_generated-transaction:~ PERIODICEXPR`.
|
||||||
|
|
||||||
Periodic transactions are generated within some forecast period.
|
Periodic transactions are generated within some forecast period.
|
||||||
By default, this
|
This begins on:
|
||||||
|
- the start date supplied to the `--forecast` argument, if present
|
||||||
- begins on the later of
|
- otherwise, the later of
|
||||||
- the report start date if specified with -b/-p/date:
|
- the report start date if specified with -b/-p/date:
|
||||||
- the day after the latest normal (non-periodic) transaction in the journal,
|
- the day after the latest normal (non-periodic) transaction in the journal, if any
|
||||||
or today if there are no normal transactions.
|
- otherwise today.
|
||||||
|
It ends on:
|
||||||
- ends on the report end date if specified with -e/-p/date:,
|
- the end date supplied to the `--forecast` argument, if present
|
||||||
or 6 months (180 days) from today.
|
- otherwise the report end date if specified with -e/-p/date:
|
||||||
|
- otherwise 180 days (6 months) from today.
|
||||||
|
|
||||||
This means that periodic transactions will begin only after the latest
|
This means that periodic transactions will begin only after the latest
|
||||||
recorded transaction. And a recorded transaction dated in the future can
|
recorded transaction. And a recorded transaction dated in the future can
|
||||||
|
|||||||
@ -196,21 +196,6 @@ $ hledger -f - reg --forecast date:202001
|
|||||||
2020-01-28 (a) 1,000.00 USD 2,000.00 USD
|
2020-01-28 (a) 1,000.00 USD 2,000.00 USD
|
||||||
>=0
|
>=0
|
||||||
|
|
||||||
<
|
|
||||||
2021-01-01
|
|
||||||
(a) 1000
|
|
||||||
|
|
||||||
~ daily
|
|
||||||
(a) 1
|
|
||||||
|
|
||||||
# 11. Forecast transactions are generated up to the day before the requested end date
|
|
||||||
$ hledger -f - reg -b 2021-01-01 -e 2021-01-05 --forecast
|
|
||||||
2021-01-01 (a) 1000 1000
|
|
||||||
2021-01-02 (a) 1 1001
|
|
||||||
2021-01-03 (a) 1 1002
|
|
||||||
2021-01-04 (a) 1 1003
|
|
||||||
>=0
|
|
||||||
|
|
||||||
<
|
<
|
||||||
2021-09-01 Normal Balance Assertion Works
|
2021-09-01 Normal Balance Assertion Works
|
||||||
Checking = -60
|
Checking = -60
|
||||||
@ -224,7 +209,7 @@ $ hledger -f - reg -b 2021-01-01 -e 2021-01-05 --forecast
|
|||||||
Checking = -120
|
Checking = -120
|
||||||
Costs
|
Costs
|
||||||
|
|
||||||
# 12. Forecast transactions work with balance assignments
|
# 11. Forecast transactions work with balance assignments
|
||||||
$ hledger -f - print -x --forecast -e 2021-11
|
$ hledger -f - print -x --forecast -e 2021-11
|
||||||
2021-09-01 Normal Balance Assertion Works
|
2021-09-01 Normal Balance Assertion Works
|
||||||
Checking -60 = -60
|
Checking -60 = -60
|
||||||
@ -250,7 +235,7 @@ $ hledger -f - print -x --forecast -e 2021-11
|
|||||||
income:client1 -10 USD
|
income:client1 -10 USD
|
||||||
assets:receivables:contractor1
|
assets:receivables:contractor1
|
||||||
|
|
||||||
# 13. Generated forecast for weekday transactions
|
# 12. Generated forecast for weekday transactions
|
||||||
$ hledger -f - reg --forecast -b "2021-09-01" -e "2021-09-15" --forecast -w 100
|
$ hledger -f - reg --forecast -b "2021-09-01" -e "2021-09-15" --forecast -w 100
|
||||||
2021-09-01 income:client1 -10 USD -10 USD
|
2021-09-01 income:client1 -10 USD -10 USD
|
||||||
assets:receivables:contractor1 10 USD 0
|
assets:receivables:contractor1 10 USD 0
|
||||||
@ -282,7 +267,7 @@ $ hledger -f - reg --forecast -b "2021-09-01" -e "2021-09-15" --forecast -w 100
|
|||||||
income:client1 -10 USD
|
income:client1 -10 USD
|
||||||
assets:receivables:contractor1
|
assets:receivables:contractor1
|
||||||
|
|
||||||
# 14. Generated forecast for weekend transactions
|
# 13. Generated forecast for weekend transactions
|
||||||
$ hledger -f - reg --forecast -b "2021-09-01" -e "2021-09-15" --forecast -w 100
|
$ hledger -f - reg --forecast -b "2021-09-01" -e "2021-09-15" --forecast -w 100
|
||||||
2021-09-04 income:client1 -10 USD -10 USD
|
2021-09-04 income:client1 -10 USD -10 USD
|
||||||
assets:receivables:contractor1 10 USD 0
|
assets:receivables:contractor1 10 USD 0
|
||||||
@ -293,3 +278,68 @@ $ hledger -f - reg --forecast -b "2021-09-01" -e "2021-09-15" --forecast -w 100
|
|||||||
2021-09-12 income:client1 -10 USD -10 USD
|
2021-09-12 income:client1 -10 USD -10 USD
|
||||||
assets:receivables:contractor1 10 USD 0
|
assets:receivables:contractor1 10 USD 0
|
||||||
>=0
|
>=0
|
||||||
|
|
||||||
|
<
|
||||||
|
2021-01-01
|
||||||
|
(a) 1000
|
||||||
|
|
||||||
|
~ daily
|
||||||
|
(a) 1
|
||||||
|
|
||||||
|
# 14. Arguments to --forecast take precedence over anything. Only generate up to the day before the end date.
|
||||||
|
$ hledger -f - reg --forecast="2020-01-01..2020-01-05" -b 2019-12-01 -e 2020-02-01 -H
|
||||||
|
2020-01-01 (a) 1 1
|
||||||
|
2020-01-02 (a) 1 2
|
||||||
|
2020-01-03 (a) 1 3
|
||||||
|
2020-01-04 (a) 1 4
|
||||||
|
>=0
|
||||||
|
|
||||||
|
# 15. With no arguments to --forecast, we use the report start date if it's after the journal end date.
|
||||||
|
$ hledger -f - reg --forecast -b 2021-02-01 -e 2021-02-05 -H
|
||||||
|
2021-02-01 (a) 1 1001
|
||||||
|
2021-02-02 (a) 1 1002
|
||||||
|
2021-02-03 (a) 1 1003
|
||||||
|
2021-02-04 (a) 1 1004
|
||||||
|
>=0
|
||||||
|
|
||||||
|
# 16. With no arguments to --forecast, we use journal end date if it's after the report start date.
|
||||||
|
$ hledger -f - reg --forecast -b 2020-12-01 -e 2021-01-05 -H
|
||||||
|
2021-01-01 (a) 1000 1000
|
||||||
|
2021-01-02 (a) 1 1001
|
||||||
|
2021-01-03 (a) 1 1002
|
||||||
|
2021-01-04 (a) 1 1003
|
||||||
|
>=0
|
||||||
|
|
||||||
|
# 17. With no arguments to --forecast, and no report start, generate from journal end to 180 days from today.
|
||||||
|
# We use here the fact that we are at least 180 days from 2021-01-01. This test will fail if you travel back in time!
|
||||||
|
$ hledger -f - reg --forecast -H
|
||||||
|
> /1 1360/
|
||||||
|
>=0
|
||||||
|
|
||||||
|
<
|
||||||
|
~ daily
|
||||||
|
(a) 1
|
||||||
|
|
||||||
|
# 18. No real transactions.
|
||||||
|
# Arguments to --forecast take precedence over anything. Only generate up to the day before the end date.
|
||||||
|
$ hledger -f - reg --forecast="2020-01-01..2020-01-05" -b 2019-12-01 -e 2020-01-05 -H
|
||||||
|
2020-01-01 (a) 1 1
|
||||||
|
2020-01-02 (a) 1 2
|
||||||
|
2020-01-03 (a) 1 3
|
||||||
|
2020-01-04 (a) 1 4
|
||||||
|
>=0
|
||||||
|
|
||||||
|
# 19. No real transactions.
|
||||||
|
# With no arguments to --forecast, we use the report start date.
|
||||||
|
$ hledger -f - reg --forecast -b 2021-02-01 -e 2021-02-05 -H
|
||||||
|
2021-02-01 (a) 1 1
|
||||||
|
2021-02-02 (a) 1 2
|
||||||
|
2021-02-03 (a) 1 3
|
||||||
|
2021-02-04 (a) 1 4
|
||||||
|
>=0
|
||||||
|
|
||||||
|
# 20. No real transactions.
|
||||||
|
# With no arguments to --forecast, and no report start, generate from today to 180 days from today.
|
||||||
|
$ hledger -f - reg --forecast -H
|
||||||
|
> /1 180/
|
||||||
|
>=0
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user