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.
This commit is contained in:
Dmitry Astapov 2017-11-22 21:00:57 +00:00
parent 597e9c47c9
commit 50b4d76ce9

View File

@ -219,6 +219,14 @@ renderPostingCommentDates p = p { pcomment = comment' }
-- 2018/11/29
-- hi $1.00
-- <BLANKLINE>
-- >>> 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