Commit e9130ca7 authored by Jérome Perrin's avatar Jérome Perrin

calendar: More fixes with exceptions when not repeating

The fixes from !630
were not enough, exceptions set on days were calendar did not repeat
were also confusing other exceptions after this.

Simplify implementation a lot, instead of keeping track of the next
exception date, start by building a set of all exceptions dates and
use membership of this set as a criterion to skip exceptions.

/reviewed-on !1030
parent 1764c526
Pipeline #7693 failed with stage
......@@ -137,13 +137,9 @@ class PresencePeriod(Movement, PeriodicityMixin):
exception_value_list = self.getCalendarPeriodExceptionValueList()
exception_date_list = [x.getExceptionDate() \
for x in exception_value_list]
exception_date_list = [x for x in exception_date_list if x is not None]
exception_date_list.sort()
if len(exception_date_list) != 0:
current_exception_date = exception_date_list.pop(0).Date()
else:
current_exception_date = None
exception_date_set = set(
[x.Date() for x in exception_date_list if x is not None]
)
start_date = self.getStartDate()
if start_date is not None:
stop_date = self.getStopDate(start_date)
......@@ -155,32 +151,7 @@ class PresencePeriod(Movement, PeriodicityMixin):
next_start_date = self.getNextPeriodicalDate(addToDate(start_date, day=-1))
while (next_start_date is not None) and \
(next_start_date <= periodicity_stop_date):
# Check that next_start_date is not an exception
if (current_exception_date is not None) and \
(current_exception_date == next_start_date.Date()):
# We match an exception date
# So, don't return this value
# Update the next exception date
if len(exception_date_list) != 0:
current_exception_date = exception_date_list.pop(0).Date()
else:
current_exception_date = None
elif (current_exception_date is not None) and \
(current_exception_date < next_start_date.Date()):
# SQL method don't like iterator
# yield (next_start_date, next_start_date+duration)
result.append({'start_date': next_start_date,
'stop_date': addToDate(next_start_date, second=second_duration),
'quantity': self.getQuantity()})
# Update the next exception date
if len(exception_date_list) != 0:
current_exception_date = exception_date_list.pop(0).Date()
else:
current_exception_date = None
else:
# SQL method don't like iterator
# yield (next_start_date, next_start_date+duration)
if next_start_date.Date() not in exception_date_set:
result.append({'start_date': next_start_date,
'stop_date': addToDate(next_start_date, second=second_duration),
'quantity': self.getQuantity()})
......
......@@ -1767,6 +1767,67 @@ class TestCalendar(ERP5ReportTestCase):
to_date=DateTime(2016, 1, 31).latestTime(),
node_uid=person.getUid()))
def test_GroupCalendarPeriodExceptionWhenNoAvailabilityAndValidExceptions(self):
"""Variation on test_GroupCalendarPeriodExceptionWhenNoAvailability, also
check that other exceptions works fine.
"""
group_calendar = self.portal.group_calendar_module.newContent(
portal_type='Group Calendar')
group_calendar_period = group_calendar.newContent(
portal_type='Group Presence Period')
group_calendar_period.setStartDate('2016/01/01 09:00')
group_calendar_period.setStopDate('2016/01/01 16:00')
group_calendar_period.setPeriodicityStopDate('2016/02/01')
group_calendar_period.setResourceValue(
self.portal.portal_categories.calendar_period_type.type1)
group_calendar_period.setPeriodicityWeekDayList(
('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', ))
group_calendar.confirm()
# Add two exceptions on 2016/01/02 (which does not repeat) and on 2016/01/04 (
# which is a valid exception).
#
# January 2016
# Su Mo Tu We Th Fr Sa
# 1 ?2
# 3 -4 5 6 7 8 9
# 10 11 12 13 14 15 16
# 17 18 19 20 21 22 23
# 24 25 26 27 28 29 30
# 31
group_calendar_period.newContent(
portal_type="Calendar Exception",
exception_date=DateTime(2016, 1, 2))
group_calendar_period.newContent(
portal_type="Calendar Exception",
exception_date=DateTime(2016, 1, 4))
person = self.portal.person_module.newContent(portal_type='Person')
assignment = self.portal.group_calendar_assignment_module.newContent(
specialise_value=group_calendar,
resource_value=self.portal.service_module.consulting_service,
start_date=DateTime(2016, 1, 1).earliestTime(),
stop_date=DateTime(2016, 1, 31).latestTime(),
destination_value=person)
assignment.confirm()
self.tic()
self.assertTrue(assignment.asMovementList())
days = [m.getStartDate().Date() for m in assignment.asMovementList()]
self.assertIn('2016/01/01', days)
self.assertNotIn('2016/01/02', days)
self.assertNotIn('2016/01/03', days)
self.assertNotIn('2016/01/04', days)
self.assertIn('2016/01/05', days)
self.assertIn('2016/01/06', days)
self.assertEqual(
7 * 60 * 60 * 20, # 7 hours per day, 20 "business days" ( because 04 is not counted)
self.portal.portal_simulation.getInventory(
portal_type=self.portal.getPortalCalendarPeriodTypeList(),
from_date=DateTime(2016, 1, 1).earliestTime(),
to_date=DateTime(2016, 1, 31).latestTime(),
node_uid=person.getUid()))
def test_PersonModule_viewLeaveRequestReport(self):
# in this test, type1 is the type for presences, type2 & type3 are types
# for leaves.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment