[REF] resource: remove deprecated compatibility and rename methods

Old methods are still present since a long time and are deprecated since
saas-3. This compatibility layer adds unnecessary complexity to the module
API. Those methods should now be removed. Some renaming is also performed
to ease resource api understanding, notably to better differentiate
internal methods from other methods.

All addons are updated accordingly.
This commit is contained in:
Thibault Delavallée
2017-02-27 14:04:48 +01:00
parent 06f36ddbe9
commit be01aaa99f
8 changed files with 98 additions and 222 deletions
@@ -299,11 +299,11 @@ class BaseAutomation(models.Model):
@api.model
def _check_delay(self, action, record, record_dt):
if action.trg_date_calendar_id and action.trg_date_range_type == 'day':
return action.trg_date_calendar_id.schedule_days_get_date(
return action.trg_date_calendar_id.plan_days(
action.trg_date_range,
day_date=fields.Datetime.from_string(record_dt),
compute_leaves=True,
)[0]
)
else:
delay = DATE_RANGE_FUNCTION[action.trg_date_range_type](action.trg_date_range)
return fields.Datetime.from_string(record_dt) + delay
+1 -1
View File
@@ -285,7 +285,7 @@ class Holidays(models.Model):
employee = self.env['hr.employee'].browse(employee_id)
resource = employee.resource_id
if resource and resource.calendar_id:
hours = resource.calendar_id.get_working_hours(from_dt, to_dt, resource_id=resource.id, compute_leaves=True)
hours = resource.calendar_id.get_work_hours_count(from_dt, to_dt, resource_id=resource.id, compute_leaves=True)
uom_hour = resource.calendar_id.uom_id
uom_day = self.env.ref('product.product_uom_day')
if uom_hour and uom_day:
+1 -1
View File
@@ -334,7 +334,7 @@ class HrPayslip(models.Model):
day_to = fields.Datetime.from_string(date_to)
nb_of_days = (day_to - day_from).days + 1
for day in range(0, nb_of_days):
working_hours_on_day = contract.working_hours.working_hours_on_day(day_from + timedelta(days=day))
working_hours_on_day = contract.working_hours.get_work_hours_count(day_from + timedelta(days=day), False)
if working_hours_on_day:
#the employee had to work
leave_type = was_on_leave(contract.employee_id.id, day_from + timedelta(days=day))
+1 -1
View File
@@ -206,7 +206,7 @@ class MrpWorkcenterProductivity(models.Model):
d2 = fields.Datetime.from_string(blocktime.date_end)
diff = d2 - d1
if (blocktime.loss_type not in ('productive', 'performance')) and blocktime.workcenter_id.calendar_id:
r = blocktime.workcenter_id.calendar_id.get_working_hours(d1, d2, resource_id=blocktime.workcenter_id.resource_id.id)
r = blocktime.workcenter_id.calendar_id.get_work_hours_count(d1, d2, resource_id=blocktime.workcenter_id.resource_id.id)
blocktime.duration = round(r * 60, 2)
else:
blocktime.duration = round(diff.total_seconds() / 60.0, 2)
+2 -2
View File
@@ -90,7 +90,7 @@ class ProjectIssue(models.Model):
dt_date_open = fields.Datetime.from_string(issue.date_open)
issue.day_open = (dt_date_open - dt_create_date).total_seconds() / (24.0 * 3600)
if issue.project_id.resource_calendar_id:
issue.working_hours_open = issue.project_id.resource_calendar_id.get_working_hours(
issue.working_hours_open = issue.project_id.resource_calendar_id.get_work_hours_count(
dt_create_date, dt_date_open,
compute_leaves=True, resource_id=False)
else:
@@ -100,7 +100,7 @@ class ProjectIssue(models.Model):
dt_date_closed = fields.Datetime.from_string(issue.date_closed)
issue.day_close = (dt_date_closed - dt_create_date).total_seconds() / (24.0 * 3600)
if issue.project_id.resource_calendar_id:
issue.working_hours_close = issue.project_id.resource_calendar_id.get_working_hours(
issue.working_hours_close = issue.project_id.resource_calendar_id.get_work_hours_count(
dt_create_date, dt_date_closed,
compute_leaves=True, resource_id=False)
else:
+52 -154
View File
@@ -14,6 +14,11 @@ from odoo.exceptions import ValidationError
from odoo.tools.float_utils import float_compare
def seconds(td):
assert isinstance(td, timedelta)
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.**6
class ResourceCalendar(models.Model):
""" Calendar model for a resource. It has
@@ -67,7 +72,7 @@ class ResourceCalendar(models.Model):
# Utility methods
# --------------------------------------------------
def interval_clean(self, intervals):
def _interval_clean(self, intervals):
""" Utility method that sorts and removes overlapping inside datetime
intervals. The intervals are sorted based on increasing starting datetime.
Overlapping intervals are merged into a single one.
@@ -92,7 +97,7 @@ class ResourceCalendar(models.Model):
return cleaned
@api.model
def interval_remove_leaves(self, interval, leave_intervals):
def _interval_remove_leaves(self, interval, leave_intervals):
""" Utility method that remove leave intervals from a base interval:
- clean the leave intervals, to have an ordered list of not-overlapping
@@ -121,7 +126,7 @@ class ResourceCalendar(models.Model):
if leave_intervals is None:
leave_intervals = []
intervals = []
leave_intervals = self.interval_clean(leave_intervals)
leave_intervals = self._interval_clean(leave_intervals)
current_interval = [interval[0], interval[1]]
for leave in leave_intervals:
if leave[1] <= current_interval[0]:
@@ -138,7 +143,8 @@ class ResourceCalendar(models.Model):
intervals.append((current_interval[0], current_interval[1]))
return intervals
def interval_schedule_hours(self, intervals, hour, remove_at_end=True):
@api.model
def _interval_schedule_hours(self, intervals, hour, remove_at_end=True):
""" Schedule hours in intervals. The last matching interval is truncated
to match the specified hours.
@@ -176,7 +182,7 @@ class ResourceCalendar(models.Model):
# --------------------------------------------------
@api.multi
def get_attendances_for_weekday(self, day_dt):
def _get_day_attendances(self, day_dt):
""" Given a day datetime, return matching attendances """
self.ensure_one()
weekday = day_dt.weekday()
@@ -191,7 +197,7 @@ class ResourceCalendar(models.Model):
return attendances
@api.multi
def get_weekdays(self):
def _get_weekdays(self):
""" Return the list of weekdays that contain at least one working
interval. """
self.ensure_one()
@@ -199,7 +205,7 @@ class ResourceCalendar(models.Model):
return list(weekdays)
@api.multi
def get_next_day(self, day_date):
def _get_next_work_day(self, day_date):
""" Get following date of day_date, based on resource.calendar. If no
calendar is provided, just return the next day.
@@ -207,7 +213,7 @@ class ResourceCalendar(models.Model):
:return date: next day of calendar, or just next day """
self.ensure_one()
weekdays = self.get_weekdays()
weekdays = self._get_weekdays()
base_index = -1
for weekday in weekdays:
@@ -223,15 +229,15 @@ class ResourceCalendar(models.Model):
return day_date + relativedelta(days=days)
@api.multi
def get_previous_day(self, day_date):
""" Get previous date of day_date, based on resource.calendar. If no
def _get_previous_work_day(self, day_date):
""" Get previous date of day_date, based on work.calendar. If no
calendar is provided, just return the previous day.
:param date day_date: current day as a date
:return date: previous day of calendar, or just previous day """
self.ensure_one()
weekdays = self.get_weekdays()
weekdays = self._get_weekdays()
weekdays.reverse()
base_index = -1
@@ -248,8 +254,8 @@ class ResourceCalendar(models.Model):
return day_date + relativedelta(days=days)
@api.multi
def get_leave_intervals(self, resource_id=None,
start_datetime=None, end_datetime=None):
def _get_leave_intervals(self, resource_id=None,
start_datetime=None, end_datetime=None):
"""Get the leaves of the calendar. Leaves can be filtered on the resource,
the start datetime or the end datetime.
@@ -280,8 +286,8 @@ class ResourceCalendar(models.Model):
return leaves
@api.multi
def get_working_intervals_of_day(self, start_dt=None, end_dt=None,
leaves=None, compute_leaves=False, resource_id=None):
def _get_day_work_intervals(self, start_dt=None, end_dt=None,
leaves=None, compute_leaves=False, resource_id=None):
""" Get the working intervals of the day based on calendar. This method
handle leaves that come directly from the leaves parameter or can be computed.
@@ -321,14 +327,14 @@ class ResourceCalendar(models.Model):
end_dt = start_dt.replace(hour=23, minute=59, second=59)
else:
work_limits.append((end_dt, end_dt.replace(hour=23, minute=59, second=59)))
assert start_dt.date() == end_dt.date(), 'get_working_intervals_of_day is restricted to one day'
assert start_dt.date() == end_dt.date(), '_get_day_work_intervals is restricted to one day'
intervals = []
work_dt = start_dt.replace(hour=0, minute=0, second=0)
working_intervals = []
tz_info = fields.Datetime.context_timestamp(self, work_dt).tzinfo
for calendar_working_day in self.get_attendances_for_weekday(start_dt):
for calendar_working_day in self._get_day_attendances(start_dt):
dt_f = work_dt.replace(hour=0, minute=0, second=0) + timedelta(seconds=(calendar_working_day.hour_from * 3600))
dt_t = work_dt.replace(hour=0, minute=0, second=0) + timedelta(seconds=(calendar_working_day.hour_to * 3600))
@@ -338,54 +344,48 @@ 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)
working_intervals += self._interval_remove_leaves(working_interval, work_limits)
# find leave intervals
if leaves is None and compute_leaves:
leaves = self.get_leave_intervals(resource_id=resource_id)
leaves = self._get_leave_intervals(resource_id=resource_id)
# filter according to leaves
for interval in working_intervals:
work_intervals = self.interval_remove_leaves(interval, leaves)
work_intervals = self._interval_remove_leaves(interval, leaves)
intervals += work_intervals
return intervals
@api.multi
def get_working_hours_of_date(self, start_dt=None, end_dt=None,
leaves=None, compute_leaves=False, resource_id=None):
""" Get the working hours of the day based on calendar. This method uses
get_working_intervals_of_day to have the work intervals of the day. It
then calculates the number of hours contained in those intervals. """
res = timedelta()
intervals = self.get_working_intervals_of_day(
start_dt, end_dt, leaves,
compute_leaves, resource_id)
for interval in intervals:
res += interval[1] - interval[0]
return seconds(res) / 3600.0
# --------------------------------------------------
# Main computation API
# --------------------------------------------------
@api.multi
def get_working_hours(self, start_dt, end_dt, compute_leaves=False,
resource_id=None):
hours = 0.0
def get_work_hours_count(self, start_dt, end_dt, compute_leaves=False, resource_id=None):
if not end_dt:
end_dt = start_dt.replace(hour=23, minute=59, second=59)
res = timedelta()
for day in rrule.rrule(rrule.DAILY,
dtstart=start_dt,
until=end_dt,
byweekday=self.get_weekdays()):
byweekday=self._get_weekdays()):
day_start_dt = day.replace(hour=0, minute=0, second=0)
if start_dt and day.date() == start_dt.date():
day_start_dt = start_dt
day_end_dt = day.replace(hour=23, minute=59, second=59)
if end_dt and day.date() == end_dt.date():
day_end_dt = end_dt
hours += self.get_working_hours_of_date(
intervals = self._get_day_work_intervals(
start_dt=day_start_dt, end_dt=day_end_dt,
compute_leaves=compute_leaves, resource_id=resource_id)
return hours
for interval in intervals:
res += interval[1] - interval[0]
return seconds(res) / 3600.0
# --------------------------------------------------
# Hours scheduling
# Scheduling API
# --------------------------------------------------
@api.multi
@@ -433,12 +433,12 @@ class ResourceCalendar(models.Model):
else:
call_args['start_dt'] = current_datetime
working_intervals = self.get_working_intervals_of_day(**call_args)
working_intervals = self._get_day_work_intervals(**call_args)
if working_intervals:
if backwards:
working_intervals.reverse()
new_working_intervals = self.interval_schedule_hours(working_intervals, remaining_hours, not backwards)
new_working_intervals = self._interval_schedule_hours(working_intervals, remaining_hours, not backwards)
if backwards:
new_working_intervals.reverse()
@@ -452,33 +452,20 @@ class ResourceCalendar(models.Model):
intervals = intervals + new_working_intervals
# get next day
if backwards:
current_datetime = datetime.datetime.combine(self.get_previous_day(current_datetime), datetime.time(23, 59, 59))
current_datetime = datetime.datetime.combine(self._get_previous_work_day(current_datetime), datetime.time(23, 59, 59))
else:
current_datetime = datetime.datetime.combine(self.get_next_day(current_datetime), datetime.time())
current_datetime = datetime.datetime.combine(self._get_next_work_day(current_datetime), datetime.time())
# avoid infinite loops
iterations += 1
return intervals
@api.multi
def schedule_hours_get_date(self, hours, day_dt=None,
compute_leaves=False, resource_id=None):
""" Wrapper on _schedule_hours: return the beginning/ending datetime of
an hours scheduling. """
def plan_hours(self, hours, day_dt=None, compute_leaves=False, resource_id=None):
""" Return datetime after having planned hours """
res = self._schedule_hours(hours, day_dt, compute_leaves, resource_id)
return res and res[0][0] or False
@api.multi
def schedule_hours(self, hours, day_dt=None,
compute_leaves=False, resource_id=None):
""" Wrapper on _schedule_hours: return the working intervals of an hours
scheduling. """
return self._schedule_hours(hours, day_dt, compute_leaves, resource_id)
# --------------------------------------------------
# Days scheduling
# --------------------------------------------------
@api.multi
def _schedule_days(self, days, day_date=None, compute_leaves=False,
resource_id=None):
@@ -516,7 +503,7 @@ class ResourceCalendar(models.Model):
current_datetime = day_date.replace(hour=0, minute=0, second=0)
while planned_days < days and iterations < 100:
working_intervals = self.get_working_intervals_of_day(
working_intervals = self._get_day_work_intervals(
current_datetime,
compute_leaves=compute_leaves, resource_id=resource_id)
if not self or working_intervals: # no calendar -> no working hours, but day is considered as worked
@@ -524,98 +511,20 @@ class ResourceCalendar(models.Model):
intervals += working_intervals
# get next day
if backwards:
current_datetime = self.get_previous_day(current_datetime)
current_datetime = self._get_previous_work_day(current_datetime)
else:
current_datetime = self.get_next_day(current_datetime)
current_datetime = self._get_next_work_day(current_datetime)
# avoid infinite loops
iterations += 1
return intervals
@api.multi
def schedule_days_get_date(self, days, day_date=None, compute_leaves=False, resource_id=None):
""" Wrapper on _schedule_days: return the beginning/ending datetime of
a days scheduling. """
def plan_days(self, days, day_date=None, compute_leaves=False, resource_id=None):
""" Returns the datetime of a days scheduling. """
res = self._schedule_days(days, day_date, compute_leaves, resource_id)
return res and res[-1][1] or False
@api.multi
def schedule_days(self, days, day_date=None, compute_leaves=False, resource_id=None):
""" Wrapper on _schedule_days: return the working intervals of a days
scheduling. """
return self._schedule_days(days, day_date, compute_leaves, resource_id)
# --------------------------------------------------
# Compatibility / to clean / to remove
# --------------------------------------------------
@api.multi
def working_hours_on_day(self, day):
""" Used in hr_payroll/hr_payroll.py
:deprecated: Odoo saas-3. Use get_working_hours_of_date instead. Note:
since saas-3, take hour/minutes into account, not just the whole day."""
if isinstance(day, datetime.datetime):
day = day.replace(hour=0, minute=0)
return self.get_working_hours_of_date(start_dt=day)
@api.multi
def interval_min_get(self, dt_from, hours, resource=False):
""" Schedule hours backwards. Used in mrp_operations/mrp_operations.py.
:deprecated: Odoo saas-3. Use schedule_hours instead. Note: since
saas-3, counts leave hours instead of all-day leaves."""
return self.schedule_hours(
hours * -1.0,
day_dt=dt_from.replace(minute=0, second=0),
compute_leaves=True, resource_id=resource
)
@api.model
def interval_get_multi(self, date_and_hours_by_cal, resource=False, byday=True):
""" Used in mrp_operations/mrp_operations.py (default parameters) and in
interval_get()
:deprecated: Odoo saas-3. Use schedule_hours instead. Note:
Byday was not used. Since saas-3, counts Leave hours instead of all-day leaves."""
res = {}
for dt_str, hours, calendar_id in date_and_hours_by_cal:
result = self.browse(calendar_id).schedule_hours(
hours,
day_dt=fields.Datetime.from_string(dt_str).replace(second=0),
compute_leaves=True, resource_id=resource,
)
res[(dt_str, hours, calendar_id)] = result
return res
@api.multi
def interval_get(self, dt_from, hours, resource=False, byday=True):
""" Unifier of interval_get_multi. Used in: mrp_operations/mrp_operations.py,
crm/crm_lead.py (res given).
:deprecated: Odoo saas-3. Use get_working_hours instead."""
self.ensure_one()
res = self.interval_get_multi(
[(fields.Datetime.to_string(dt_from), hours, self.id)], resource, byday)[(fields.Datetime.to_string(dt_from), hours, self.id)]
return res
@api.multi
def interval_hours_get(self, dt_from, dt_to, resource=False):
""" Unused wrapper.
:deprecated: Odoo saas-3. Use get_working_hours instead."""
return self._interval_hours_get(dt_from, dt_to, resource_id=resource)
@api.multi
def _interval_hours_get(self, dt_from, dt_to, resource_id=False, timezone_from_uid=None, exclude_leaves=True):
""" Computes working hours between two dates, taking always same hour/minuts.
:deprecated: Odoo saas-3. Use get_working_hours instead. Note: since saas-3,
now resets hour/minuts. Now counts leave hours instead of all-day leaves."""
return self.get_working_hours(
dt_from, dt_to,
compute_leaves=(not exclude_leaves), resource_id=resource_id,
)
class ResourceCalendarAttendance(models.Model):
_name = "resource.calendar.attendance"
@@ -639,12 +548,6 @@ class ResourceCalendarAttendance(models.Model):
calendar_id = fields.Many2one("resource.calendar", string="Resource's Calendar", required=True, ondelete='cascade')
def hours_time_string(hours):
""" convert a number of hours (float) into a string with format '%H:%M' """
minutes = int(round(hours * 60))
return "%02d:%02d" % divmod(minutes, 60)
class ResourceResource(models.Model):
_name = "resource.resource"
_description = "Resource Detail"
@@ -718,7 +621,7 @@ class ResourceResource(models.Model):
days (inclusive)
:rtype: list(datetime.date)
"""
working_intervals = self.calendar_id.get_working_intervals_of_day
working_intervals = self.calendar_id._get_day_work_intervals
# rrule coerces date inputs to datetimes (with time=0) and yields
# datetimes (with time=0 if freq >= daily)
for dt in rrule.rrule(rrule.DAILY, dtstart=from_date, until=to_date):
@@ -753,8 +656,3 @@ class ResourceCalendarLeaves(models.Model):
def onchange_resource(self):
if self.resource_id:
self.calendar_id = self.resource_id.calendar_id
def seconds(td):
assert isinstance(td, timedelta)
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.**6
+35 -57
View File
@@ -7,9 +7,8 @@ from datetime import datetime, timedelta, date
from dateutil.relativedelta import relativedelta
from odoo.fields import Date, Datetime
from odoo.tools import float_compare
from odoo.addons.resource.models.resource import seconds
from odoo.addons.resource.tests.common import TestResourceCommon
from odoo.tests import TransactionCase
class TestIntervals(TestResourceCommon):
@@ -45,7 +44,7 @@ class TestIntervals(TestResourceCommon):
]
def test_interval_clean(self):
cleaned_intervals = self.env['resource.calendar'].interval_clean(self.intervals)
cleaned_intervals = self.env['resource.calendar']._interval_clean(self.intervals)
self.assertEqual(len(cleaned_intervals), 3)
# First interval: 03, unchanged
self.assertEqual(cleaned_intervals[0], (Datetime.from_string('2013-02-03 08:00:00'), Datetime.from_string('2013-02-03 10:00:00')))
@@ -56,14 +55,14 @@ class TestIntervals(TestResourceCommon):
def test_interval_remove(self):
working_interval = (Datetime.from_string('2013-02-04 08:00:00'), Datetime.from_string('2013-02-04 18:00:00'))
result = self.env['resource.calendar'].interval_remove_leaves(working_interval, self.intervals)
result = self.env['resource.calendar']._interval_remove_leaves(working_interval, self.intervals)
self.assertEqual(len(result), 1)
# First interval: 04, 14-17
self.assertEqual(result[0], (Datetime.from_string('2013-02-04 14:00:00'), Datetime.from_string('2013-02-04 17:00:00')))
def test_interval_schedule_hours(self):
cleaned_intervals = self.env['resource.calendar'].interval_clean(self.intervals)
result = self.env['resource.calendar'].interval_schedule_hours(cleaned_intervals, 5.5)
cleaned_intervals = self.env['resource.calendar']._interval_clean(self.intervals)
result = self.env['resource.calendar']._interval_schedule_hours(cleaned_intervals, 5.5)
self.assertEqual(len(result), 2)
# First interval: 03, 8-10 untouched
self.assertEqual(result[0], (Datetime.from_string('2013-02-03 08:00:00'), Datetime.from_string('2013-02-03 10:00:00')))
@@ -71,9 +70,9 @@ class TestIntervals(TestResourceCommon):
self.assertEqual(result[1], (Datetime.from_string('2013-02-04 08:00:00'), Datetime.from_string('2013-02-04 11:30:00')))
def test_interval_schedule_hours_backwards(self):
cleaned_intervals = self.env['resource.calendar'].interval_clean(self.intervals)
cleaned_intervals = self.env['resource.calendar']._interval_clean(self.intervals)
cleaned_intervals.reverse()
result = self.env['resource.calendar'].interval_schedule_hours(cleaned_intervals, 5.5, remove_at_end=False)
result = self.env['resource.calendar']._interval_schedule_hours(cleaned_intervals, 5.5, remove_at_end=False)
self.assertEqual(len(result), 2)
# First interval: 03, 8-10 untouched
self.assertEqual(result[0], (Datetime.from_string('2013-02-04 17:00:00'), Datetime.from_string('2013-02-04 21:00:00')))
@@ -84,68 +83,68 @@ class TestIntervals(TestResourceCommon):
class TestCalendarBasics(TestResourceCommon):
def test_calendar_weekdays(self):
weekdays = self.calendar.get_weekdays()
weekdays = self.calendar._get_weekdays()
self.assertEqual(weekdays, [1, 4])
def test_calendar_next_day(self):
# Test: next day: next day after day1 is day4
date = self.calendar.get_next_day(day_date=Date.from_string('2013-02-12'))
date = self.calendar._get_next_work_day(day_date=Date.from_string('2013-02-12'))
self.assertEqual(date, self.date2.date())
# Test: next day: next day after day4 is (day1+7)
date = self.calendar.get_next_day(day_date=Date.from_string('2013-02-15'))
date = self.calendar._get_next_work_day(day_date=Date.from_string('2013-02-15'))
self.assertEqual(date, self.date1.date() + relativedelta(days=7))
# Test: next day: next day after day4+1 is (day1+7)
date = self.calendar.get_next_day(day_date=Date.from_string('2013-02-15') + relativedelta(days=1))
date = self.calendar._get_next_work_day(day_date=Date.from_string('2013-02-15') + relativedelta(days=1))
self.assertEqual(date, self.date1.date() + relativedelta(days=7))
# Test: next day: next day after day1-1 is day1
date = self.calendar.get_next_day(day_date=Date.from_string('2013-02-12') + relativedelta(days=-1))
date = self.calendar._get_next_work_day(day_date=Date.from_string('2013-02-12') + relativedelta(days=-1))
self.assertEqual(date, self.date1.date())
def test_calendar_previous_day(self):
# Test: previous day: previous day before day1 is (day4-7)
date = self.calendar.get_previous_day(day_date=Date.from_string('2013-02-12'))
date = self.calendar._get_previous_work_day(day_date=Date.from_string('2013-02-12'))
self.assertEqual(date, self.date2.date() + relativedelta(days=-7))
# Test: previous day: previous day before day4 is day1
date = self.calendar.get_previous_day(day_date=Date.from_string('2013-02-15'))
date = self.calendar._get_previous_work_day(day_date=Date.from_string('2013-02-15'))
self.assertEqual(date, self.date1.date())
# Test: previous day: previous day before day4+1 is day4
date = self.calendar.get_previous_day(day_date=Date.from_string('2013-02-15') + relativedelta(days=1))
date = self.calendar._get_previous_work_day(day_date=Date.from_string('2013-02-15') + relativedelta(days=1))
self.assertEqual(date, self.date2.date())
# Test: previous day: previous day before day1-1 is (day4-7)
date = self.calendar.get_previous_day(day_date=Date.from_string('2013-02-12') + relativedelta(days=-1))
date = self.calendar._get_previous_work_day(day_date=Date.from_string('2013-02-12') + relativedelta(days=-1))
self.assertEqual(date, self.date2.date() + relativedelta(days=-7))
def test_calendar_working_day_intervals_no_leaves(self):
# Test: day0 without leaves: 1 interval
intervals = self.calendar.get_working_intervals_of_day(start_dt=Datetime.from_string('2013-02-12 09:08:07'))
intervals = self.calendar._get_day_work_intervals(start_dt=Datetime.from_string('2013-02-12 09:08:07'))
self.assertEqual(len(intervals), 1)
self.assertEqual(intervals[0], (Datetime.from_string('2013-02-12 09:08:07'), Datetime.from_string('2013-02-12 16:00:00')))
# Test: day1, beginning at 10:30 -> work from 10:30 (arrival) until 16:00
intervals = self.calendar.get_working_intervals_of_day(start_dt=Datetime.from_string('2013-02-19 10:30:00'))
intervals = self.calendar._get_day_work_intervals(start_dt=Datetime.from_string('2013-02-19 10:30:00'))
self.assertEqual(len(intervals), 1)
self.assertEqual(intervals[0], (Datetime.from_string('2013-02-19 10:30:00'), Datetime.from_string('2013-02-19 16:00:00')))
# Test: day3 without leaves: 2 interval
intervals = self.calendar.get_working_intervals_of_day(start_dt=Datetime.from_string('2013-02-15 10:11:12'))
intervals = self.calendar._get_day_work_intervals(start_dt=Datetime.from_string('2013-02-15 10:11:12'))
self.assertEqual(len(intervals), 2)
self.assertEqual(intervals[0], (Datetime.from_string('2013-02-15 10:11:12'), Datetime.from_string('2013-02-15 13:00:00')))
self.assertEqual(intervals[1], (Datetime.from_string('2013-02-15 16:00:00'), Datetime.from_string('2013-02-15 23:00:00')))
def test_calendar_working_day_intervals_leaves_generic(self):
# Test: day0 with leaves outside range: 1 interval
intervals = self.calendar.get_working_intervals_of_day(start_dt=Datetime.from_string('2013-02-12 07:00:00'), compute_leaves=True)
intervals = self.calendar._get_day_work_intervals(start_dt=Datetime.from_string('2013-02-12 07:00:00'), compute_leaves=True)
self.assertEqual(len(intervals), 1)
self.assertEqual(intervals[0], (Datetime.from_string('2013-02-12 08:00:00'), Datetime.from_string('2013-02-12 16:00:00')))
# Test: day0 with leaves: 2 intervals because of leave between 9 ans 12, ending at 15:45:30
intervals = self.calendar.get_working_intervals_of_day(start_dt=Datetime.from_string('2013-02-19 08:15:00'),
intervals = self.calendar._get_day_work_intervals(start_dt=Datetime.from_string('2013-02-19 08:15:00'),
end_dt=Datetime.from_string('2013-02-19 15:45:30'),
compute_leaves=True)
self.assertEqual(len(intervals), 2)
@@ -154,7 +153,7 @@ class TestCalendarBasics(TestResourceCommon):
def test_calendar_working_day_intervals_leaves_resource(self):
# Test: day1+14 on leave, with resource leave computation
intervals = self.calendar.get_working_intervals_of_day(
intervals = self.calendar._get_day_work_intervals(
Datetime.from_string('2013-02-26 07:00:00'),
compute_leaves=True,
resource_id=self.resource1_id
@@ -170,76 +169,60 @@ class TestCalendarBasics(TestResourceCommon):
'date_from': self.date2 + relativedelta(days=7),
'date_to': False,
})
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date2)
intervals = self.calendar._get_day_work_intervals(start_dt=self.date2)
self.assertEqual(intervals, [(Datetime.from_string('2013-02-15 10:11:12'), Datetime.from_string('2013-02-15 13:00:00'))])
attendance.write({
'date_from': False,
'date_to': self.date2 - relativedelta(days=7),
})
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date2)
intervals = self.calendar._get_day_work_intervals(start_dt=self.date2)
self.assertEqual(intervals, [(Datetime.from_string('2013-02-15 10:11:12'), Datetime.from_string('2013-02-15 13:00:00'))])
attendance.write({
'date_from': self.date2 + relativedelta(days=7),
'date_to': self.date2 - relativedelta(days=7),
})
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date2)
intervals = self.calendar._get_day_work_intervals(start_dt=self.date2)
self.assertEqual(intervals, [(Datetime.from_string('2013-02-15 10:11:12'), Datetime.from_string('2013-02-15 13:00:00'))])
attendance.write({
'date_from': self.date2,
'date_to': self.date2,
})
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date2)
intervals = self.calendar._get_day_work_intervals(start_dt=self.date2)
self.assertEqual(len(intervals), 2)
self.assertEqual(intervals[0], (Datetime.from_string('2013-02-15 10:11:12'), Datetime.from_string('2013-02-15 13:00:00')))
self.assertEqual(intervals[1], (Datetime.from_string('2013-02-15 16:00:00'), Datetime.from_string('2013-02-15 23:00:00')))
def test_calendar_working_hours_of_date(self):
# Test: day1, beginning at 10:30 -> work from 10:30 (arrival) until 16:00
wh = self.calendar.get_working_hours_of_date(start_dt=Datetime.from_string('2013-02-19 10:30:00'))
wh = self.calendar.get_work_hours_count(Datetime.from_string('2013-02-19 10:30:00'), Datetime.from_string('2013-02-19 18:00:00'))
self.assertEqual(wh, 5.5, 'resource_calendar: wrong working interval / day time computing')
class ResourceWorkingHours(TestResourceCommon):
def test_calendar_working_hours(self):
# old API: resource without leaves
# res: 2 weeks -> 40 hours
res = self.calendar._interval_hours_get(
Datetime.from_string('2013-02-12 06:00:00'),
Datetime.from_string('2013-02-22 23:00:00'),
resource_id=self.resource1_id, exclude_leaves=True)
self.assertEqual(res, 40.0)
# new API: resource without leaves
# res: 2 weeks -> 40 hours
res = self.calendar.get_working_hours(
res = self.calendar.get_work_hours_count(
Datetime.from_string('2013-02-12 06:00:00'),
Datetime.from_string('2013-02-22 23:00:00'),
compute_leaves=False, resource_id=self.resource1_id)
self.assertEqual(res, 40.0)
def test_calendar_working_hours_leaves(self):
# old API: resource and leaves
# res: 2 weeks -> 40 hours - (3+4) leave hours
res = self.calendar._interval_hours_get(
Datetime.from_string('2013-02-12 06:00:00'),
Datetime.from_string('2013-02-22 23:00:00'),
resource_id=self.resource1_id, exclude_leaves=False)
self.assertEqual(res, 33.0)
# new API: resource and leaves
# res: 2 weeks -> 40 hours - (3+4) leave hours
res = self.calendar.get_working_hours(
res = self.calendar.get_work_hours_count(
Datetime.from_string('2013-02-12 06:00:00'),
Datetime.from_string('2013-02-22 23:00:00'),
compute_leaves=True, resource_id=self.resource1_id)
self.assertEqual(res, 33.0)
def test_calendar_hours_scheduling_backward(self):
res = self.calendar.schedule_hours(-40, day_dt=Datetime.from_string('2013-02-12 09:00:00'))
res = self.calendar._schedule_hours(-40, day_dt=Datetime.from_string('2013-02-12 09:00:00'))
# current day, limited at 09:00 because of day_dt specified -> 1 hour
self.assertEqual(res[-1], (Datetime.from_string('2013-02-12 08:00:00'), Datetime.from_string('2013-02-12 09:00:00')))
# previous days: 5+7 hours / 8 hours / 5+7 hours -> 32 hours
@@ -258,7 +241,7 @@ class ResourceWorkingHours(TestResourceCommon):
self.assertEqual(seconds(td) / 3600.0, 40.0)
def test_calendar_hours_scheduling_forward(self):
res = self.calendar.schedule_hours(40, day_dt=Datetime.from_string('2013-02-12 09:00:00'))
res = self.calendar._schedule_hours(40, day_dt=Datetime.from_string('2013-02-12 09:00:00'))
self.assertEqual(res[0], (Datetime.from_string('2013-02-12 09:00:00'), Datetime.from_string('2013-02-12 16:00:00')))
self.assertEqual(res[1], (Datetime.from_string('2013-02-15 08:00:00'), Datetime.from_string('2013-02-15 13:00:00')))
self.assertEqual(res[2], (Datetime.from_string('2013-02-15 16:00:00'), Datetime.from_string('2013-02-15 23:00:00')))
@@ -273,7 +256,7 @@ class ResourceWorkingHours(TestResourceCommon):
self.assertEqual(seconds(td) / 3600.0, 40.0)
def test_calendar_hours_scheduling_forward_leaves_resource(self):
res = self.calendar.schedule_hours(
res = self.calendar._schedule_hours(
40, day_dt=Datetime.from_string('2013-02-12 09:00:00'),
compute_leaves=True, resource_id=self.resource1_id
)
@@ -293,12 +276,12 @@ class ResourceWorkingHours(TestResourceCommon):
self.assertEqual(seconds(td) / 3600.0, 40.0)
def test_calendar_days_scheduling(self):
res = self.calendar.schedule_days_get_date(5, day_date=Datetime.from_string('2013-02-12 09:08:07') )
res = self.calendar.plan_days(5, day_date=Datetime.from_string('2013-02-12 09:08:07') )
self.assertEqual(res.date(), Datetime.from_string('2013-02-26 00:00:00').date(), 'resource_calendar: wrong days scheduling')
res = self.calendar.schedule_days_get_date(-2, day_date=Datetime.from_string('2013-02-12 09:08:07') )
res = self.calendar.plan_days(-2, day_date=Datetime.from_string('2013-02-12 09:08:07') )
self.assertEqual(res.date(), Datetime.from_string('2013-02-08 00:00:00').date(), 'resource_calendar: wrong days scheduling')
res = self.calendar.schedule_days_get_date(
res = self.calendar.plan_days(
5, day_date=Datetime.from_string('2013-02-12 09:08:07'),
compute_leaves=True, resource_id=self.resource1_id)
self.assertEqual(res.date(), Datetime.from_string('2013-03-01 00:00:00').date(), 'resource_calendar: wrong days scheduling')
@@ -439,8 +422,3 @@ class TestWorkDays(TestResourceCommon):
self.assertFalse(r._is_work_day(date(1932, 11, 19))) # sat
self.assertFalse(r._is_work_day(date(1932, 11, 20))) # sun
self.assertFalse(r._is_work_day(date(1932, 12, 6))) # personal leave
def seconds(td):
assert isinstance(td, timedelta)
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.**6
+4 -4
View File
@@ -22,8 +22,8 @@ class ResourceCalendar(models.Model):
# Keep as it takes into account times
@api.multi
def get_leave_intervals(self, resource_id=None,
start_datetime=None, end_datetime=None):
def _get_leave_intervals(self, resource_id=None,
start_datetime=None, end_datetime=None):
"""Get the leaves of the calendar. Leaves can be filtered on the resource,
the start datetime or the end datetime.
@@ -60,7 +60,7 @@ class ResourceCalendar(models.Model):
# --------------------------------------------------
@api.model
def interval_remove_leaves(self, interval, leave_intervals):
def _interval_remove_leaves(self, interval, leave_intervals):
""" Utility method that remove leave intervals from a base interval:
- clean the leave intervals, to have an ordered list of not-overlapping
@@ -92,7 +92,7 @@ class ResourceCalendar(models.Model):
if leave_intervals is None:
leave_intervals = []
intervals = []
#leave_intervals = self.interval_clean(leave_intervals) NOT NECESSARY TO CLEAN HERE AS IT WOULD REMOVE GROUP INFO
#leave_intervals = self._interval_clean(leave_intervals) NOT NECESSARY TO CLEAN HERE AS IT WOULD REMOVE GROUP INFO
current_interval = list(interval)
for leave in leave_intervals:
if len(leave) > 2: