From be01aaa99ff3ad32b757dd0a61a437dac19fc2c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 10 Nov 2016 13:34:14 +0100 Subject: [PATCH] [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. --- .../base_automation/models/base_automation.py | 4 +- addons/hr_holidays/models/hr_holidays.py | 2 +- addons/hr_payroll/models/hr_payroll.py | 2 +- addons/mrp/models/mrp_workcenter.py | 2 +- addons/project_issue/models/project_issue.py | 4 +- addons/resource/models/resource.py | 206 +++++------------- addons/resource/tests/test_resource.py | 92 +++----- addons/stock_calendar/models/resource.py | 8 +- 8 files changed, 98 insertions(+), 222 deletions(-) diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py index a03ff7678bc..24267f72821 100644 --- a/addons/base_automation/models/base_automation.py +++ b/addons/base_automation/models/base_automation.py @@ -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 diff --git a/addons/hr_holidays/models/hr_holidays.py b/addons/hr_holidays/models/hr_holidays.py index b074517ddb6..84a37f09c9a 100644 --- a/addons/hr_holidays/models/hr_holidays.py +++ b/addons/hr_holidays/models/hr_holidays.py @@ -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: diff --git a/addons/hr_payroll/models/hr_payroll.py b/addons/hr_payroll/models/hr_payroll.py index f104c46de04..4be849c9b9a 100644 --- a/addons/hr_payroll/models/hr_payroll.py +++ b/addons/hr_payroll/models/hr_payroll.py @@ -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)) diff --git a/addons/mrp/models/mrp_workcenter.py b/addons/mrp/models/mrp_workcenter.py index a46dc2b193e..91f73ea9c83 100644 --- a/addons/mrp/models/mrp_workcenter.py +++ b/addons/mrp/models/mrp_workcenter.py @@ -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) diff --git a/addons/project_issue/models/project_issue.py b/addons/project_issue/models/project_issue.py index f5a77a745f4..024ab4e81b4 100644 --- a/addons/project_issue/models/project_issue.py +++ b/addons/project_issue/models/project_issue.py @@ -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: diff --git a/addons/resource/models/resource.py b/addons/resource/models/resource.py index 4867ca77294..b594df319cc 100644 --- a/addons/resource/models/resource.py +++ b/addons/resource/models/resource.py @@ -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 diff --git a/addons/resource/tests/test_resource.py b/addons/resource/tests/test_resource.py index 528e5fac854..3190c6c8345 100644 --- a/addons/resource/tests/test_resource.py +++ b/addons/resource/tests/test_resource.py @@ -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 diff --git a/addons/stock_calendar/models/resource.py b/addons/stock_calendar/models/resource.py index d63b82a3fb7..519a8e3d5e0 100644 --- a/addons/stock_calendar/models/resource.py +++ b/addons/stock_calendar/models/resource.py @@ -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: