diff --git a/planner.py b/planner.py index 6d46fad..d1dfd6a 100644 --- a/planner.py +++ b/planner.py @@ -85,8 +85,6 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView): help='the next 5 appointments based on the configured rule'), 'on_change_with_nextdates') - # rrule: frequ, dtstart, until, bymonthday - @classmethod def __setup__(cls): super(ScheduledBooking, cls).__setup__() @@ -125,12 +123,11 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView): 'year': YEARLY, 'month': MONTHLY, 'week': WEEKLY, 'day': DAILY} pweekday = { '0': MO, '1': TU, '2': WE, '3': TH, '4': FR, '5': SA, '6': SU, - '99': None} + '99': None}.get(params.get('weekday', self.weekday), None) - if (count is None) or (count > 100): - count = 100 - if count < 1: - count = 1 + if count is None: + count = 5 + count = 1 if count < 1 else 100 if count > 100 else count end_date = params.get('end_date', self.end_date) frequ = pfrequ[params.get('frequ', self.frequ)] @@ -144,11 +141,15 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView): monthday = 1 if monthday < 1 else 31 if monthday > 31 else monthday interval = params.get('interval', self.interval) + if interval is None: + interval = 1 interval = 1 if interval < 1 else 10 if interval > 10 else interval + assert (monthday is None) or (pweekday is None), \ + "weekday and monthday cannot be used together" + dtrule = rrule( - freq=frequ, - byweekday=pweekday[params.get('weekday', self.weekday)], + freq=frequ, byweekday=pweekday, dtstart=params.get('start_date', self.start_date), until=end_date, bysetpos=setpos if frequ == MONTHLY else None, diff --git a/tests/planner.py b/tests/planner.py index 0041e69..d23fa40 100644 --- a/tests/planner.py +++ b/tests/planner.py @@ -56,7 +56,7 @@ class PlannerTestCase(object): @with_transaction() def test_planner_create_job(self): - """ create job, check rule + """ create job, check rule + constraints """ Planner = Pool().get('cashbook.planner') @@ -107,7 +107,104 @@ class PlannerTestCase(object): start_date=date(2022, 5, 1), params={ 'end_date': date(2022, 9, 15), 'weekday': '2', - 'interval': 2, 'setpos': 1}), + 'interval': 2, 'setpos': 1, 'monthday': None}), [date(2022, 5, 4), date(2022, 7, 6), date(2022, 9, 7)]) + # 2nd wednesday of each 2nd month + self.assertEqual( + job._compute_dates_by_rrule( + start_date=date(2022, 5, 1), + params={ + 'end_date': date(2022, 9, 15), 'weekday': '2', + 'interval': 2, 'setpos': 2, 'monthday': None}), + [date(2022, 5, 11), date(2022, 7, 13), date(2022, 9, 14)]) + + # 2nd wednesday of each month, 6x occurences + self.assertEqual( + job._compute_dates_by_rrule( + start_date=date(2022, 5, 1), count=6, + params={ + 'weekday': '2', 'end_date': None, + 'interval': 1, 'setpos': 2, 'monthday': None}), + [date(2022, 5, 11), date(2022, 6, 8), date(2022, 7, 13), + date(2022, 8, 10), date(2022, 9, 14), date(2022, 10, 12)]) + + Planner.write(*[[job], { + 'frequ': 'year', 'start_date': date(2022, 5, 1), + 'setpos': None, 'monthday': None, 'interval': 1, + 'weekday': '99'}]) + + # invalid end_date + self.assertRaisesRegex( + UserError, + 'The value "2022-04-30" for field "End Date" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'year', 'start_date': date(2022, 5, 1), + 'end_date': date(2022, 4, 30)}]) + + # monthday and weekday used together + self.assertRaisesRegex( + UserError, + 'The value "2" for field "Day of month" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'month', 'start_date': date(2022, 5, 1), + 'monthday': 2, 'weekday': '1', 'end_date': None}]) + + # monthday out of range 1 + self.assertRaisesRegex( + UserError, + 'The value "0" for field "Day of month" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'year', 'start_date': date(2022, 5, 1), + 'monthday': 0, 'weekday': '99', 'end_date': None}]) + + # monthday out of range 2 + self.assertRaisesRegex( + UserError, + 'The value "32" for field "Day of month" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'year', 'start_date': date(2022, 5, 1), + 'monthday': 32, 'weekday': '99', 'end_date': None}]) + + # invalid usage of setpos + self.assertRaisesRegex( + UserError, + 'The value "1" for field "Occurrence" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'year', 'start_date': date(2022, 5, 1), + 'setpos': 1, 'monthday': None, 'weekday': '99', + 'end_date': None}]) + + # setpos out of range 1 + self.assertRaisesRegex( + UserError, + 'The value "0" for field "Occurrence" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'month', 'start_date': date(2022, 5, 1), + 'setpos': 0, 'monthday': None, 'weekday': '2', + 'end_date': None}]) + + # setpos out of range 2 + self.assertRaisesRegex( + UserError, + 'The value "5" for field "Occurrence" in "Job 1" of ' + + '"Scheduled Booking" is not valid according to its domain.', + Planner.write, + *[[job], { + 'frequ': 'month', 'start_date': date(2022, 5, 1), + 'setpos': 5, 'monthday': None, 'weekday': '2', + 'end_date': None}]) + # end PlannerTestCase