Add option to rule to move date of occurence to working day
This commit is contained in:
parent
e76ec5792c
commit
a84b672250
2 changed files with 93 additions and 4 deletions
46
planner.py
46
planner.py
|
@ -217,11 +217,42 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
|
||||||
used instead of the stored values, Defaults to {},
|
used instead of the stored values, Defaults to {},
|
||||||
allowed: frequ, weekday, start_date,
|
allowed: frequ, weekday, start_date,
|
||||||
end_date (preferred over 'count'),
|
end_date (preferred over 'count'),
|
||||||
monthday, interval, setpos
|
monthday, interval, setpos, move_event
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list: date values, result of rrlue
|
list: date values, result of rrlue
|
||||||
"""
|
"""
|
||||||
|
def get_moved_date(xdate, m_mode):
|
||||||
|
""" re-arrange xdate to a working day
|
||||||
|
|
||||||
|
Args:
|
||||||
|
xdate (date): date to move to a working day
|
||||||
|
move_mode (str): move mode:
|
||||||
|
nop - no operation
|
||||||
|
after/before - move date to after/before input date
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
date: re-arranged date
|
||||||
|
"""
|
||||||
|
Config = Pool().get('cashbook.configuration')
|
||||||
|
config = Config.get_singleton()
|
||||||
|
|
||||||
|
assert m_mode in ['nop', 'after', 'before'], 'invalid move_mode'
|
||||||
|
|
||||||
|
if (not config) or (m_mode == 'nop'):
|
||||||
|
return xdate
|
||||||
|
|
||||||
|
holidays = config.holiday_dates([xdate.year, xdate.year + 1])
|
||||||
|
day_cnt = (
|
||||||
|
1 if m_mode == 'after'
|
||||||
|
else -1 if m_mode == 'before' else 0)
|
||||||
|
|
||||||
|
if day_cnt != 0:
|
||||||
|
while (xdate in holidays) or (xdate.weekday() in [5, 6]):
|
||||||
|
# re-arrange
|
||||||
|
xdate = xdate + timedelta(days=day_cnt)
|
||||||
|
return xdate
|
||||||
|
|
||||||
pfrequ = {
|
pfrequ = {
|
||||||
'year': YEARLY, 'month': MONTHLY, 'week': WEEKLY, 'day': DAILY}
|
'year': YEARLY, 'month': MONTHLY, 'week': WEEKLY, 'day': DAILY}
|
||||||
pweekday = {
|
pweekday = {
|
||||||
|
@ -235,6 +266,10 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
|
||||||
end_date = params.get('end_date', self.end_date)
|
end_date = params.get('end_date', self.end_date)
|
||||||
frequ = pfrequ[params.get('frequ', self.frequ)]
|
frequ = pfrequ[params.get('frequ', self.frequ)]
|
||||||
|
|
||||||
|
move_event = params.get('move_event', self.move_event)
|
||||||
|
if move_event not in ['nop', 'before', 'after']:
|
||||||
|
move_event = 'nop'
|
||||||
|
|
||||||
setpos = params.get('setpos', self.setpos)
|
setpos = params.get('setpos', self.setpos)
|
||||||
if setpos is not None:
|
if setpos is not None:
|
||||||
setpos = 1 if setpos < 1 else 4 if setpos > 4 else setpos
|
setpos = 1 if setpos < 1 else 4 if setpos > 4 else setpos
|
||||||
|
@ -262,7 +297,12 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
|
||||||
for x in dtrule:
|
for x in dtrule:
|
||||||
if (query_date and (x.date() >= query_date)) or \
|
if (query_date and (x.date() >= query_date)) or \
|
||||||
(query_date is None):
|
(query_date is None):
|
||||||
result.append(x.date())
|
x_date = get_moved_date(x.date(), move_event)
|
||||||
|
|
||||||
|
# if date was re-arranged backwards and we are before
|
||||||
|
# query_date - skip it
|
||||||
|
if x_date >= query_date:
|
||||||
|
result.append(x_date)
|
||||||
if len(result) >= count:
|
if len(result) >= count:
|
||||||
break
|
break
|
||||||
return result
|
return result
|
||||||
|
@ -328,7 +368,7 @@ class ScheduledBooking(DeactivableMixin, ModelSQL, ModelView):
|
||||||
|
|
||||||
@fields.depends(
|
@fields.depends(
|
||||||
'start_date', 'end_date', 'frequ', 'weekday', 'monthday',
|
'start_date', 'end_date', 'frequ', 'weekday', 'monthday',
|
||||||
'interval', 'setpos')
|
'interval', 'setpos', 'move_event')
|
||||||
def on_change_with_nextdates(self, name=None):
|
def on_change_with_nextdates(self, name=None):
|
||||||
""" Calculates the next 5 appointments based on the configured rule,
|
""" Calculates the next 5 appointments based on the configured rule,
|
||||||
returns a formatted date list
|
returns a formatted date list
|
||||||
|
|
|
@ -170,7 +170,9 @@ class PlannerTestCase(object):
|
||||||
def test_planner_create_job(self):
|
def test_planner_create_job(self):
|
||||||
""" create job, check rule + constraints
|
""" create job, check rule + constraints
|
||||||
"""
|
"""
|
||||||
Planner = Pool().get('cashbook.planner')
|
pool = Pool()
|
||||||
|
Planner = pool.get('cashbook.planner')
|
||||||
|
Config = pool.get('cashbook.configuration')
|
||||||
|
|
||||||
job = self.prep_create_job()
|
job = self.prep_create_job()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -243,6 +245,53 @@ class PlannerTestCase(object):
|
||||||
[date(2022, 5, 11), date(2022, 6, 8), date(2022, 7, 13),
|
[date(2022, 5, 11), date(2022, 6, 8), date(2022, 7, 13),
|
||||||
date(2022, 8, 10), date(2022, 9, 14), date(2022, 10, 12)])
|
date(2022, 8, 10), date(2022, 9, 14), date(2022, 10, 12)])
|
||||||
|
|
||||||
|
# set up holidays
|
||||||
|
cfg1 = Config(
|
||||||
|
holidays='01-01;05-01;easter:+1;easter:-2;ascension;whitsun:+1')
|
||||||
|
cfg1.save()
|
||||||
|
# 1st of may, should be moved to 2nd of may
|
||||||
|
self.assertEqual(
|
||||||
|
job._compute_dates_by_rrule(
|
||||||
|
query_date=date(2022, 4, 25), count=3,
|
||||||
|
params={
|
||||||
|
'end_date': None, 'start_date': date(2022, 5, 1),
|
||||||
|
'move_event': 'after', 'weekday': None,
|
||||||
|
'setpos': None, 'interval': 1, 'frequ': 'year',
|
||||||
|
'monthday': None}),
|
||||||
|
[date(2022, 5, 2), date(2023, 5, 2), date(2024, 5, 2)])
|
||||||
|
# easter of 2022, occurence-date moved to tuesday after easter'22
|
||||||
|
self.assertEqual(
|
||||||
|
job._compute_dates_by_rrule(
|
||||||
|
query_date=date(2022, 4, 10), count=3,
|
||||||
|
params={
|
||||||
|
'end_date': None, 'start_date': date(2022, 4, 17),
|
||||||
|
'move_event': 'after', 'weekday': None,
|
||||||
|
'setpos': None,
|
||||||
|
'interval': 1, 'frequ': 'month', 'monthday': None}),
|
||||||
|
[date(2022, 4, 19), date(2022, 5, 17), date(2022, 6, 17)])
|
||||||
|
# easter of 2022, monthly, occurence-date moved to
|
||||||
|
# thursday before easter'22
|
||||||
|
self.assertEqual(
|
||||||
|
job._compute_dates_by_rrule(
|
||||||
|
query_date=date(2022, 4, 10), count=3,
|
||||||
|
params={
|
||||||
|
'end_date': None, 'start_date': date(2022, 4, 17),
|
||||||
|
'move_event': 'before', 'weekday': None,
|
||||||
|
'setpos': None,
|
||||||
|
'interval': 1, 'frequ': 'month', 'monthday': None}),
|
||||||
|
[date(2022, 4, 14), date(2022, 5, 17), date(2022, 6, 17)])
|
||||||
|
# easter of 2022, monthly, check next occurence after easter
|
||||||
|
# recompute date at moved occurence-date+1
|
||||||
|
self.assertEqual(
|
||||||
|
job._compute_dates_by_rrule(
|
||||||
|
query_date=date(2022, 4, 15), count=3,
|
||||||
|
params={
|
||||||
|
'end_date': None, 'start_date': date(2022, 4, 17),
|
||||||
|
'move_event': 'before', 'weekday': None,
|
||||||
|
'setpos': None,
|
||||||
|
'interval': 1, 'frequ': 'month', 'monthday': None}),
|
||||||
|
[date(2022, 5, 17), date(2022, 6, 17), date(2022, 7, 15)])
|
||||||
|
|
||||||
Planner.write(*[[job], {
|
Planner.write(*[[job], {
|
||||||
'frequ': 'year', 'start_date': date(2022, 5, 1),
|
'frequ': 'year', 'start_date': date(2022, 5, 1),
|
||||||
'setpos': None, 'monthday': None, 'interval': 1,
|
'setpos': None, 'monthday': None, 'interval': 1,
|
||||||
|
|
Loading…
Reference in a new issue