diff --git a/hledger-lib/Hledger/Data/Dates.hs b/hledger-lib/Hledger/Data/Dates.hs index 6c4a7a959..163003cdc 100644 --- a/hledger-lib/Hledger/Data/Dates.hs +++ b/hledger-lib/Hledger/Data/Dates.hs @@ -63,6 +63,7 @@ module Hledger.Data.Dates ( spanIntersect, spansIntersect, spanDefaultsFrom, + spanValidDefaultsFrom, spanExtend, spanUnion, spansUnion, @@ -348,10 +349,43 @@ spanIntersect (DateSpan b1 e1) (DateSpan b2 e2) = DateSpan (laterDefinite b1 b2) -- | Fill any unspecified dates in the first span with the dates from -- the second one (if specified there). Sort of a one-way spanIntersect. +-- This one can create an invalid span that'll always be empty. +-- +-- >>> :{ +-- DateSpan (Just $ Exact $ fromGregorian 2024 1 1) Nothing +-- `spanDefaultsFrom` +-- DateSpan (Just $ Exact $ fromGregorian 2024 1 1) (Just $ Exact $ fromGregorian 2024 1 2) +-- :} +-- DateSpan 2024-01-01 +-- +-- >>> :{ +-- DateSpan (Just $ Exact $ fromGregorian 2025 1 1) Nothing +-- `spanDefaultsFrom` +-- DateSpan (Just $ Exact $ fromGregorian 2024 1 1) (Just $ Exact $ fromGregorian 2024 1 2) +-- :} +-- DateSpan 2025-01-01..2024-01-01 +-- +spanDefaultsFrom :: DateSpan -> DateSpan -> DateSpan spanDefaultsFrom (DateSpan a1 b1) (DateSpan a2 b2) = DateSpan a b where a = if isJust a1 then a1 else a2 b = if isJust b1 then b1 else b2 +-- | A smarter version of spanDefaultsFrom that avoids creating invalid +-- spans ending before they begin. Kept separate for now to reduce risk. +-- +-- >>> :{ +-- DateSpan (Just $ Exact $ fromGregorian 2025 1 1) Nothing +-- `spanValidDefaultsFrom` +-- DateSpan (Just $ Exact $ fromGregorian 2024 1 1) (Just $ Exact $ fromGregorian 2024 1 2) +-- :} +-- DateSpan 2025-01-01.. +-- +spanValidDefaultsFrom :: DateSpan -> DateSpan -> DateSpan +spanValidDefaultsFrom s1 s2 = + case s1 `spanDefaultsFrom` s2 of + DateSpan b e | b >= e -> s1 + s -> s + -- | Calculate the union of two datespans. -- If either span is open-ended, the union will be too. -- diff --git a/hledger-lib/Hledger/Data/PeriodicTransaction.hs b/hledger-lib/Hledger/Data/PeriodicTransaction.hs index d73e8a7d7..77e165d4f 100644 --- a/hledger-lib/Hledger/Data/PeriodicTransaction.hs +++ b/hledger-lib/Hledger/Data/PeriodicTransaction.hs @@ -215,7 +215,7 @@ runPeriodicTransaction verbosetags PeriodicTransaction{..} requestedspan = alltxnspans = splitSpan adjust ptinterval span' where -- If the PT does not specify start or end dates, we take them from the requestedspan. - span' = ptspan `spanDefaultsFrom` requestedspan + span' = ptspan `spanValidDefaultsFrom` requestedspan -- Unless the PT specified a start date explicitly, we will adjust the start date to the previous interval boundary. adjust = isNothing $ spanStart span' diff --git a/hledger-lib/Hledger/Reports/MultiBalanceReport.hs b/hledger-lib/Hledger/Reports/MultiBalanceReport.hs index c8b6b7fd9..9573abcbf 100644 --- a/hledger-lib/Hledger/Reports/MultiBalanceReport.hs +++ b/hledger-lib/Hledger/Reports/MultiBalanceReport.hs @@ -390,7 +390,7 @@ generatePeriodicReport makeRow treeAmt flatAmt ropts colspans acct = PeriodicReport colspans (buildAndSort acct) totalsrow where -- Build report rows and sort them - buildAndSort = dbg5 "generatePeriodicReport buildAndSort" . case accountlistmode_ ropts of {} + buildAndSort = dbg5 "generatePeriodicReport buildAndSort" . case accountlistmode_ ropts of ALTree | sort_amount_ ropts -> buildRows . sortTreeByAmount ALFlat | sort_amount_ ropts -> sortFlatByAmount . buildRows _ -> buildRows . sortAccountTreeByDeclaration diff --git a/hledger-lib/Hledger/Reports/ReportOptions.hs b/hledger-lib/Hledger/Reports/ReportOptions.hs index 01fb0d3b2..654436b4d 100644 --- a/hledger-lib/Hledger/Reports/ReportOptions.hs +++ b/hledger-lib/Hledger/Reports/ReportOptions.hs @@ -793,9 +793,8 @@ reportSpanHelper bothdates j ReportSpec{_rsQuery=query, _rsReportOpts=ropts} = pricespan = dbg3 "pricespan" . DateSpan Nothing $ case value_ ropts of Just (AtEnd _) -> fmap (Exact . addDays 1) . maximumMay . map pddate $ jpricedirectives j _ -> Nothing - -- If the requested span is open-ended, close it using the journal's start and end dates. - -- This can still be the null (open) span if the journal is empty. - requestedspan' = dbg3 "requestedspan'" $ requestedspan `spanDefaultsFrom` (journalspan `spanExtend` pricespan) + -- If the requested span has open ends, fill those with the journal's start and/or end dates, if possible. + requestedspan' = dbg3 "requestedspan'" $ requestedspan `spanValidDefaultsFrom` (journalspan `spanExtend` pricespan) -- The list of interval spans enclosing the requested span. -- This list can be empty if the journal was empty, -- or if hledger-ui has added its special date:-tomorrow to the query diff --git a/hledger/Hledger/Cli/Commands/Run.hs b/hledger/Hledger/Cli/Commands/Run.hs index 4fe780a13..405957ed8 100644 --- a/hledger/Hledger/Cli/Commands/Run.hs +++ b/hledger/Hledger/Cli/Commands/Run.hs @@ -256,7 +256,7 @@ withJournalCached defaultJournalOverride cliopts cmd = do -- could use 'forecastPeriod') or to the journal end date (as -- forecast transactions are never generated before journal end -- unless specifically requested). - Just forecastspan -> forecastspan `spanDefaultsFrom` reportspan_ iopts + Just forecastspan -> forecastspan `spanValidDefaultsFrom` reportspan_ iopts -- Read stdin, or if we read it alread, use a cache -- readStdin :: InputOpts -> ExceptT String IO Journal readStdin = do diff --git a/hledger/test/balance/balance-multiperiod.test b/hledger/test/balance/balance-multiperiod.test index 3e087c6b4..f02fe6516 100644 --- a/hledger/test/balance/balance-multiperiod.test +++ b/hledger/test/balance/balance-multiperiod.test @@ -232,3 +232,23 @@ Balance changes in 2014-01-10..2014-03-09: explicit report period || 10 0 ------------------------++------------------------------------------------ || 10 100 + +# ** 19. The historical balances are shown here even though the report period contains no postings. (#2403) +< +2024-01-01 + (a) 1000 + +$ hledger -f - bal -NHY -b 2025 +Ending balances (historical) in 2025: + + || 2025-12-31 +===++============ + a || 1000 + +# ** 20. Without -H, no balance changes are shown here, even with -E. +# Should it show zero for each of the pre-report-period accounts ? +$ hledger -f - bal -NY -b 2025 +Balance changes in 2025: + + || 2025 +==++====== diff --git a/hledger/test/close.test b/hledger/test/close.test index 3e567e281..5641c050e 100644 --- a/hledger/test/close.test +++ b/hledger/test/close.test @@ -235,9 +235,10 @@ $ hledger -f- close >= # ** 16. "override the closing date ... by specifying a report period, where last day of the report period will be the closing date" +# With no data to close in the period, this is currently giving an error. XXX $ hledger -f- close -e 100000-01-01 -> /99999-12-31 closing balances/ ->= +>2 /Error: balanceDataPeriodEnds: expected initial span to have an end date/ +>=1 # ** 17. close (and print) should add trailing decimal marks when needed to posting amounts and costs. <