From 50b4d76ce98aa62232d60dcdb86b970368358cd0 Mon Sep 17 00:00:00 2001 From: Dmitry Astapov Date: Wed, 22 Nov 2017 21:00:57 +0000 Subject: [PATCH] lib: runPeriodicTransaction's start date must line up with interval This is very helpful for periodic transactions, because in budget mode you need to ensure that no periodic transactions extend past the end of the journal, and in forecast mode you need to make sure that all periodic transactions are strictly after the end of the journal. --- hledger-lib/Hledger/Data/AutoTransaction.hs | 23 ++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/hledger-lib/Hledger/Data/AutoTransaction.hs b/hledger-lib/Hledger/Data/AutoTransaction.hs index 87d5de4e1..67c6abb8f 100644 --- a/hledger-lib/Hledger/Data/AutoTransaction.hs +++ b/hledger-lib/Hledger/Data/AutoTransaction.hs @@ -219,6 +219,14 @@ renderPostingCommentDates p = p { pcomment = comment' } -- 2018/11/29 -- hi $1.00 -- +-- >>> gen "weekly from 2017" +-- *** Exception: Unable to generate transactions according to "weekly from 2017" as 2017-01-01 is not a first day of the week +-- >>> gen "monthly from 2017/5/4" +-- *** Exception: Unable to generate transactions according to "monthly from 2017/5/4" as 2017-05-04 is not a first day of the month +-- >>> gen "every quarter from 2017/1/2" +-- *** Exception: Unable to generate transactions according to "every quarter from 2017/1/2" as 2017-01-02 is not a first day of the quarter +-- >>> gen "yearly from 2017/1/14" +-- *** Exception: Unable to generate transactions according to "yearly from 2017/1/14" as 2017-01-14 is not a first day of the year runPeriodicTransaction :: PeriodicTransaction -> (DateSpan -> [Transaction]) runPeriodicTransaction pt = generate where base = nulltransaction { tpostings = ptpostings pt } @@ -227,5 +235,18 @@ runPeriodicTransaction pt = generate where (interval, effectspan) = case parsePeriodExpr errCurrent periodExpr of Left e -> error' $ "Failed to parse " ++ show (T.unpack periodExpr) ++ ": " ++ showDateParseError e - Right x -> x + Right x -> checkProperStartDate x generate jspan = [base {tdate=date} | span <- interval `splitSpan` spanIntersect effectspan jspan, let Just date = spanStart span] + checkProperStartDate (i,s) = + case (i,spanStart s) of + (Weeks _, Just d) -> checkStart d "week" + (Months _, Just d) -> checkStart d "month" + (Quarters _, Just d) -> checkStart d "quarter" + (Years _, Just d) -> checkStart d "year" + _ -> (i,s) + where + checkStart d x = + let firstDate = fixSmartDate d ("","this",x) + in + if d == firstDate then (i,s) + else error' $ "Unable to generate transactions according to "++(show periodExpr)++" as "++(show d)++" is not a first day of the "++x