[FIX] resource: force start_dt

Set up:
- Use the usual working schedule from 8:00 to 12:00 and 13:00 to 17:00.
- Set the OS and user TZ to Australia/Sidney TZ (restart your browser)
- Create a BOM with 3 work orders, taking 1, 2 and 3 minutes (you can
  use the 'Assemble Furniture' routing)
- Create a MO using the previously created BOM, e.g. for '[FURN001]
  Computer Desk'

Case 1: Plan to start the next day at 08:00, e.g. 2017-06-08

The result is amazing. The system probably hit a flaw in the space-time
continuum, which can only be explained with M-theory:
- WO1 is planned from 2017-06-08 08:00:00 to 2017-06-07 08:01:00
- WO2 is planned from 2017-06-07 08:01:00 to 2017-06-06 08:02:00
- WO3 is planned from 2017-06-06 08:02:00 to 2017-06-05 08:03:00

Case 2: Plan to start the next day at 11:00, e.g. 2017-06-08

Once again, the result is literally a piece of art:
- WO1 is planned from 2017-06-08 11:00:00 to 2017-06-08 08:01:00
- WO2 is planned from 2017-06-08 08:01:00 to 2017-06-07 08:02:00
- WO3 is planned from 2017-06-07 08:02:00 to 2017-06-06 08:03:00

To solve the problem, a first commit is made in MRP to force the end
date to be larger than the start date. That hides the issue, but it
doesn't solve it.

To prevent the system to hit the 88 mph and go back in time, we force a
'hard limit' to prevent any selection of intervals starting before the
requested start time.

opw-745905
This commit is contained in:
Nicolas Martinelli
2017-06-19 08:40:19 +02:00
parent 74918dfa37
commit 34736b0a6c
2 changed files with 54 additions and 1 deletions
+20 -1
View File
@@ -304,6 +304,11 @@ class ResourceCalendar(models.Model):
elif start_dt is None:
start_dt = datetime.datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
else:
# FORWARD-PORT UP TO SAAS-14
# Add a strict limit when searching for intervals
force_start_dt = self.env.context.get('force_start_dt')
if force_start_dt and force_start_dt < start_dt:
work_limits.append((force_start_dt.replace(hour=0, minute=0, second=0, microsecond=0), force_start_dt))
work_limits.append((start_dt.replace(hour=0, minute=0, second=0, microsecond=0), start_dt))
if end_dt is None:
end_dt = start_dt.replace(hour=23, minute=59, second=59, microsecond=999999)
@@ -335,7 +340,15 @@ class ResourceCalendar(models.Model):
dt_t.replace(tzinfo=tz_info).astimezone(pytz.UTC).replace(tzinfo=None),
calendar_working_day.id
)
working_intervals += self.interval_remove_leaves(working_interval, work_limits)
# FORWARD-PORT UP TO SAAS-14
# Add a strict limit when searching for intervals (yeah, once again!)
if self.env.context.get('force_start_dt'):
for wi in self.interval_remove_leaves(working_interval, work_limits):
if wi[0] >= self.env.context['force_start_dt']:
working_intervals += [wi]
else:
working_intervals += self.interval_remove_leaves(working_interval, work_limits)
# find leave intervals
if leaves is None and compute_leaves:
@@ -423,6 +436,12 @@ class ResourceCalendar(models.Model):
"""
if day_dt is None:
day_dt = datetime.datetime.now()
elif day_dt is not None and hours > 0:
# FORWARD-PORT UP TO SAAS-14
# FIXME: think about a better fix... However, solved from saas-15 thanks to refactoring
# Make sure the to keep the original start date when searching for intervals, since a
# difference in day may occur depending on the TZ.
self = self.with_context(force_start_dt=day_dt)
backwards = (hours < 0)
hours = abs(hours)
intervals = []
+34
View File
@@ -477,6 +477,40 @@ class TestResource(TestResourceCommon):
resource_id = self.env.ref('resource.resource_analyst').copy()
self.assertTrue(resource_id, 'Unable to Duplicate Resource')
# FORWARD-PORT UP TO SAAS-14
# Test already in Saas-15
def test_80_resource_schedule_tz(self):
# Call schedule_hours for a user in Autralia, Sydney (GMT+10)
# Two cases:
# - start at 2013-02-15 08:00:00 => 2013-02-14 21:00:00 in UTC
# - start at 2013-02-15 11:00:00 => 2013-02-15 00:00:00 in UTC
tz_context = dict(tz='Australia/Sydney')
self.env.user.with_context(tz_context).write({'tz': 'Australia/Sydney'})
calendar = self.calendar.with_context(tz_context)
self.env['resource.calendar.attendance'].create({
'name': 'Day3 - 1',
'dayofweek': '3',
'hour_from': 8,
'hour_to': 12,
'calendar_id': calendar.id,
})
self.env['resource.calendar.attendance'].create({
'name': 'Day3 - 2',
'dayofweek': '3',
'hour_from': 13,
'hour_to': 17,
'calendar_id': calendar.id,
})
hours = 1.0/60.0
start_dt = Datetime.from_string('2013-02-14 21:00:00')
res = calendar.schedule_hours(hours, start_dt)
self.assertEqual([(start_dt, start_dt.replace(minute=1))], res, 'resource_calendar: wrong schedule_hours computation')
start_dt = Datetime.from_string('2013-02-15 00:00:00')
res = calendar.schedule_hours(hours, start_dt)
self.assertEqual([(start_dt, start_dt.replace(minute=1))], res, 'resource_calendar: wrong schedule_hours computation')
WAR_START = date(1932, 11, 2)
WAR_END = date(1932, 12, 10)