[MERGE] resource: Migration to new API

This commit is contained in:
Yannick Tivisse
2016-07-13 12:54:32 +02:00
16 changed files with 511 additions and 636 deletions
+5 -5
View File
@@ -163,10 +163,10 @@ class Holidays(models.Model):
('validate1', 'Second Approval'),
('validate', 'Approved')
], string='Status', readonly=True, track_visibility='onchange', copy=False, default='confirm',
help="The status is set to 'To Submit', when a holiday request is created.\
\nThe status is 'To Approve', when holiday request is confirmed by user.\
\nThe status is 'Refused', when holiday request is refused by manager.\
\nThe status is 'Approved', when holiday request is approved by manager.")
help="The status is set to 'To Submit', when a holiday request is created." +
"\nThe status is 'To Approve', when holiday request is confirmed by user." +
"\nThe status is 'Refused', when holiday request is refused by manager." +
"\nThe status is 'Approved', when holiday request is approved by manager.")
payslip_status = fields.Boolean('Reported in last payslips',
help='Green this button when the leave has been taken into account in the payslip.')
report_note = fields.Text('HR Comments')
@@ -284,7 +284,7 @@ class Holidays(models.Model):
uom_hour = resource.calendar_id.uom_id
uom_day = self.env.ref('product.product_uom_day')
if uom_hour and uom_day:
return self.env['product.uom']._compute_qty_obj(uom_hour, hours[0], uom_day)
return self.env['product.uom']._compute_qty_obj(uom_hour, hours, uom_day)
time_delta = to_dt - from_dt
return math.ceil(time_delta.days + float(time_delta.seconds) / 86400)
+1 -1
View File
@@ -330,7 +330,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 = self.env['resource.calendar'].working_hours_on_day(contract.working_hours, day_from + timedelta(days=day))
working_hours_on_day = contract.working_hours.working_hours_on_day(day_from + timedelta(days=day))
if working_hours_on_day:
#the employee had to work
leave_type = was_on_leave(contract.employee_id.id, day_from + timedelta(days=day))
+6 -20
View File
@@ -94,35 +94,21 @@ class ProjectIssue(models.Model):
@api.depends('create_date', 'date_closed', 'date_open')
def _compute_day(self):
for issue in self:
# if the working hours on the project are not defined, use default ones (8 -> 12 and 13 -> 17 * 5), represented by None
calendar_id = None
if issue.project_id and issue.project_id.resource_calendar_id:
calendar_id = issue.project_id.resource_calendar_id.id
# if the working hours on the project are not defined, use default ones (8 -> 12 and 13 -> 17 * 5)
calendar = issue.project_id.resource_calendar_id
dt_create_date = fields.Datetime.from_string(issue.create_date)
if issue.date_open:
dt_date_open = fields.Datetime.from_string(issue.date_open)
issue.day_open = (dt_date_open - dt_create_date).total_seconds() / (24.0 * 3600)
# FIXME when resource.calendar is migrated to new api
# Old api call because get_working_hours uses get_weekdays
# which has a different behavior if the given id is None.
issue.working_hours_open = self.pool['resource.calendar'].get_working_hours(
self.env.cr, self.env.uid, calendar_id, dt_create_date, dt_date_open,
compute_leaves=True, resource_id=False, default_interval=(8, 16),
context=self.env.context
)
issue.working_hours_open = calendar.get_working_hours(dt_create_date, dt_date_open,
compute_leaves=True, resource_id=False, default_interval=(8, 16))
if issue.date_closed:
dt_date_closed = fields.Datetime.from_string(issue.date_closed)
issue.day_close = (dt_date_closed - dt_create_date).total_seconds() / (24.0 * 3600)
# FIXME when resource.calendar is migrated to new api
# Old api call because get_working_hours uses get_weekdays
# which has a different behavior if the given id is None.
issue.working_hours_close = self.pool['resource.calendar'].get_working_hours(
self.env.cr, self.env.uid, calendar_id, dt_create_date, dt_date_closed,
compute_leaves=True, resource_id=False, default_interval=(8, 16),
context=self.env.context
)
issue.working_hours_close = calendar.get_working_hours(dt_create_date, dt_date_closed,
compute_leaves=True, resource_id=False, default_interval=(8, 16))
@api.multi
@api.depends('create_date', 'date_action_last', 'date_last_stage_update')
+1 -1
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import resource
import models
+5 -12
View File
@@ -2,10 +2,9 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name' : 'Resource',
'version' : '1.1',
'category' : 'Hidden',
'website' : 'http://www.openerp.com',
'name': 'Resource',
'version': '1.1',
'category': 'Hidden',
'description': """
Module for resource management.
===============================
@@ -18,13 +17,7 @@ associated to every resource. It also manages the leaves of every resource.
'data': [
'security/ir.model.access.csv',
'security/resource_security.xml',
'resource_view.xml',
'views/resource_views.xml',
],
'demo': ['resource_demo.xml'],
'test': [
'test/resource.yml',
'test/duplicate_resource.yml',
],
'installable': True,
'auto_install': False,
'demo': ['data/resource_demo.xml'],
}
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<!-- Example employee -->
@@ -121,5 +120,4 @@
<field name="date_to" eval="time.strftime('%Y-%m-%d 11:00:00')"/>
</record>
</data>
</openerp>
</odoo>
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import resource
@@ -2,21 +2,19 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
import functools
import pytz
from datetime import timedelta
from dateutil import rrule
from dateutil.relativedelta import relativedelta
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
from operator import itemgetter
from openerp import tools
from openerp.osv import fields, osv
from openerp.tools.float_utils import float_compare
from openerp.tools.translate import _
from openerp.exceptions import UserError
import pytz
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
from odoo.tools.float_utils import float_compare
class resource_calendar(osv.osv):
class ResourceCalendar(models.Model):
""" Calendar model for a resource. It has
- attendance_ids: list of resource.calendar.attendance that are a working
@@ -30,19 +28,15 @@ class resource_calendar(osv.osv):
_name = "resource.calendar"
_description = "Resource Calendar"
_columns = {
'name': fields.char("Name", required=True),
'company_id': fields.many2one('res.company', 'Company', required=False),
'attendance_ids': fields.one2many('resource.calendar.attendance', 'calendar_id', 'Working Time', copy=True),
'manager': fields.many2one('res.users', 'Workgroup Manager'),
'leave_ids': fields.one2many(
'resource.calendar.leaves', 'calendar_id', 'Leaves',
help=''
),
}
_defaults = {
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.calendar', context=context)
}
name = fields.Char(required=True)
company_id = fields.Many2one('res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get())
attendance_ids = fields.One2many(
'resource.calendar.attendance', 'calendar_id', string='Working Time',
copy=True)
manager = fields.Many2one('res.users', string='Workgroup Manager')
leave_ids = fields.One2many(
'resource.calendar.leaves', 'calendar_id', string='Leaves')
# --------------------------------------------------
# Utility methods
@@ -72,7 +66,8 @@ class resource_calendar(osv.osv):
cleaned.append(tuple(working_interval))
return cleaned
def interval_remove_leaves(self, cr, uid, interval, leave_intervals, context=None):
@api.model
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
@@ -112,7 +107,6 @@ class resource_calendar(osv.osv):
current_interval[1] = leave[0]
intervals.append((current_interval[0], current_interval[1]))
current_interval = [leave[1], interval[1]]
# if current_interval[0] <= leave[1] <= current_interval[1]:
if current_interval[0] <= leave[1]:
current_interval[0] = leave[1]
if current_interval and current_interval[0] < interval[1]: # remove intervals moved outside base interval due to leaves
@@ -139,14 +133,14 @@ class resource_calendar(osv.osv):
is greater than the possible scheduling in the intervals, no extra-scheduling
is done, and results == intervals. """
results = []
res = datetime.timedelta()
limit = datetime.timedelta(hours=hour)
res = timedelta()
limit = timedelta(hours=hour)
for interval in intervals:
res += interval[1] - interval[0]
if res > limit and remove_at_end:
interval = (interval[0], interval[1] + relativedelta(seconds=seconds(limit-res)))
interval = (interval[0], interval[1] + relativedelta(seconds=seconds(limit - res)))
elif res > limit:
interval = (interval[0] + relativedelta(seconds=seconds(res-limit)), interval[1])
interval = (interval[0] + relativedelta(seconds=seconds(res - limit)), interval[1])
results.append(interval)
if res > limit:
break
@@ -156,41 +150,40 @@ class resource_calendar(osv.osv):
# Date and hours computation
# --------------------------------------------------
def get_attendances_for_weekday(self, cr, uid, id, date, context=None):
@api.multi
def get_attendances_for_weekday(self, date):
""" Given a list of weekdays, return matching resource.calendar.attendance"""
calendar = self.browse(cr, uid, id, context=None)
self.ensure_one()
weekday = date.weekday()
date = date.strftime(DEFAULT_SERVER_DATE_FORMAT)
res = []
for att in calendar.attendance_ids:
if int(att.dayofweek) == weekday:
if not ((att.date_from and date < att.date_from) or (att.date_to and date > att.date_to)):
res.append(att)
return res
date = fields.Date.today()
attendances = self.env['resource.calendar.attendance']
for attendance in self.attendance_ids.filtered(lambda att: int(att.dayofweek) == weekday and
not ((att.date_from and date < att.date_from) or (att.date_to and date > att.date_to))):
attendances |= attendance
return attendances
def get_weekdays(self, cr, uid, id, default_weekdays=None, context=None):
@api.multi
def get_weekdays(self, default_weekdays=None):
""" Return the list of weekdays that contain at least one working interval.
If no id is given (no calendar), return default weekdays. """
if id is None:
if not self:
return default_weekdays if default_weekdays is not None else [0, 1, 2, 3, 4]
calendar = self.browse(cr, uid, id, context=None)
weekdays = set()
for attendance in calendar.attendance_ids:
weekdays.add(int(attendance.dayofweek))
self.ensure_one()
weekdays = set(map(int, (self.attendance_ids.mapped('dayofweek'))))
return list(weekdays)
def get_next_day(self, cr, uid, id, day_date, context=None):
@api.multi
def get_next_day(self, day_date):
""" Get following date of day_date, based on resource.calendar. If no
calendar is provided, just return the next day.
:param int id: id of a resource.calendar. If not given, simply add one day
to the submitted date.
:param date day_date: current day as a date
:return date: next day of calendar, or just next day """
if not id:
if not self:
return day_date + relativedelta(days=1)
weekdays = self.get_weekdays(cr, uid, id, context)
self.ensure_one()
weekdays = self.get_weekdays()
base_index = -1
for weekday in weekdays:
@@ -205,18 +198,18 @@ class resource_calendar(osv.osv):
return day_date + relativedelta(days=days)
def get_previous_day(self, cr, uid, id, day_date, context=None):
@api.multi
def get_previous_day(self, day_date):
""" Get previous date of day_date, based on resource.calendar. If no
calendar is provided, just return the previous day.
:param int id: id of a resource.calendar. If not given, simply remove
one day from the submitted date.
:param date day_date: current day as a date
:return date: previous day of calendar, or just previous day """
if not id:
if not self:
return day_date + relativedelta(days=-1)
weekdays = self.get_weekdays(cr, uid, id, context)
self.ensure_one()
weekdays = self.get_weekdays()
weekdays.reverse()
base_index = -1
@@ -232,9 +225,9 @@ class resource_calendar(osv.osv):
return day_date + relativedelta(days=days)
def get_leave_intervals(self, cr, uid, id, resource_id=None,
start_datetime=None, end_datetime=None,
context=None):
@api.multi
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.
@@ -250,27 +243,27 @@ class resource_calendar(osv.osv):
:return list leaves: list of tuples (start_datetime, end_datetime) of
leave intervals
"""
resource_calendar = self.browse(cr, uid, id, context=context)
self.ensure_one()
leaves = []
for leave in resource_calendar.leave_ids:
for leave in self.leave_ids:
if leave.resource_id and not resource_id == leave.resource_id.id:
continue
date_from = datetime.datetime.strptime(leave.date_from, tools.DEFAULT_SERVER_DATETIME_FORMAT)
date_from = fields.Datetime.from_string(leave.date_from)
if end_datetime and date_from > end_datetime:
continue
date_to = datetime.datetime.strptime(leave.date_to, tools.DEFAULT_SERVER_DATETIME_FORMAT)
date_to = fields.Datetime.from_string(leave.date_to)
if start_datetime and date_to < start_datetime:
continue
leaves.append((date_from, date_to))
return leaves
def get_working_intervals_of_day(self, cr, uid, id, start_dt=None, end_dt=None,
@api.multi
def get_working_intervals_of_day(self, start_dt=None, end_dt=None,
leaves=None, compute_leaves=False, resource_id=None,
default_interval=None, context=None):
default_interval=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.
:param int id: resource.calendar id; take the first one if is a list
:param datetime start_dt: datetime object that is the beginning hours
for the working intervals computation; any
working interval beginning before start_dt
@@ -300,8 +293,6 @@ class resource_calendar(osv.osv):
:return list intervals: a list of tuples (start_datetime, end_datetime)
of work intervals """
if isinstance(id, (list, tuple)):
id = id[0]
# Computes start_dt, end_dt (with default values if not set) + off-interval work limits
work_limits = []
@@ -321,17 +312,17 @@ class resource_calendar(osv.osv):
work_dt = start_dt.replace(hour=0, minute=0, second=0)
# no calendar: try to use the default_interval, then return directly
if id is None:
if not self:
working_interval = []
if default_interval:
working_interval = (start_dt.replace(hour=default_interval[0], minute=0, second=0),
start_dt.replace(hour=default_interval[1], minute=0, second=0))
intervals = self.interval_remove_leaves(cr, uid, working_interval, work_limits, context=context)
intervals = self.interval_remove_leaves(working_interval, work_limits)
return intervals
working_intervals = []
tz_info = fields.datetime.context_timestamp(cr, uid, work_dt, context=context).tzinfo
for calendar_working_day in self.get_attendances_for_weekday(cr, uid, id, start_dt, context=context):
tz_info = fields.Datetime.context_timestamp(self, work_dt).tzinfo
for calendar_working_day in self.get_attendances_for_weekday(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))
@@ -341,41 +332,42 @@ class resource_calendar(osv.osv):
dt_t.replace(tzinfo=tz_info).astimezone(pytz.UTC).replace(tzinfo=None),
calendar_working_day.id
)
working_intervals += self.interval_remove_leaves(cr, uid, working_interval, work_limits, context=context)
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(cr, uid, id, resource_id=resource_id, context=context)
leaves = self.get_leave_intervals(resource_id=resource_id)
# filter according to leaves
for interval in working_intervals:
work_intervals = self.interval_remove_leaves(cr, uid, interval, leaves, context=context)
work_intervals = self.interval_remove_leaves(interval, leaves)
intervals += work_intervals
return intervals
def get_working_hours_of_date(self, cr, uid, id, start_dt=None, end_dt=None,
@api.multi
def get_working_hours_of_date(self, start_dt=None, end_dt=None,
leaves=None, compute_leaves=False, resource_id=None,
default_interval=None, context=None):
default_interval=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 = datetime.timedelta()
res = timedelta()
intervals = self.get_working_intervals_of_day(
cr, uid, id,
start_dt, end_dt, leaves,
compute_leaves, resource_id,
default_interval, context)
default_interval)
for interval in intervals:
res += interval[1] - interval[0]
return seconds(res) / 3600.0
def get_working_hours(self, cr, uid, id, start_dt, end_dt, compute_leaves=False,
resource_id=None, default_interval=None, context=None):
@api.multi
def get_working_hours(self, start_dt, end_dt, compute_leaves=False,
resource_id=None, default_interval=None):
hours = 0.0
for day in rrule.rrule(rrule.DAILY, dtstart=start_dt,
until=(end_dt + datetime.timedelta(days=1)).replace(hour=0, minute=0, second=0),
byweekday=self.get_weekdays(cr, uid, id, context=context)):
until=(end_dt + timedelta(days=1)).replace(hour=0, minute=0, second=0),
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
@@ -383,20 +375,19 @@ class resource_calendar(osv.osv):
if end_dt and day.date() == end_dt.date():
day_end_dt = end_dt
hours += self.get_working_hours_of_date(
cr, uid, id, start_dt=day_start_dt, end_dt=day_end_dt,
start_dt=day_start_dt, end_dt=day_end_dt,
compute_leaves=compute_leaves, resource_id=resource_id,
default_interval=default_interval,
context=context)
default_interval=default_interval)
return hours
# --------------------------------------------------
# Hours scheduling
# --------------------------------------------------
def _schedule_hours(self, cr, uid, id, hours, day_dt=None,
@api.multi
def _schedule_hours(self, hours, day_dt=None,
compute_leaves=False, resource_id=None,
default_interval=None, context=None):
default_interval=None):
""" Schedule hours of work, using a calendar and an optional resource to
compute working and leave days. This method can be used backwards, i.e.
scheduling days before a deadline.
@@ -436,7 +427,7 @@ class resource_calendar(osv.osv):
iterations = 0
current_datetime = day_dt
call_args = dict(compute_leaves=compute_leaves, resource_id=resource_id, default_interval=default_interval, context=context)
call_args = dict(compute_leaves=compute_leaves, resource_id=resource_id, default_interval=default_interval)
while float_compare(remaining_hours, 0.0, precision_digits=2) in (1, 0) and iterations < 1000:
if backwards:
@@ -444,9 +435,9 @@ class resource_calendar(osv.osv):
else:
call_args['start_dt'] = current_datetime
working_intervals = self.get_working_intervals_of_day(cr, uid, id, **call_args)
working_intervals = self.get_working_intervals_of_day(**call_args)
if id is None and not working_intervals: # no calendar -> consider working 8 hours
if not self and not working_intervals: # no calendar -> consider working 8 hours
remaining_hours -= 8.0
elif working_intervals:
if backwards:
@@ -455,7 +446,7 @@ class resource_calendar(osv.osv):
if backwards:
new_working_intervals.reverse()
res = datetime.timedelta()
res = timedelta()
for interval in working_intervals:
res += interval[1] - interval[0]
remaining_hours -= (seconds(res) / 3600.0)
@@ -465,36 +456,38 @@ class resource_calendar(osv.osv):
intervals = intervals + new_working_intervals
# get next day
if backwards:
current_datetime = datetime.datetime.combine(self.get_previous_day(cr, uid, id, current_datetime, context), datetime.time(23, 59, 59))
current_datetime = datetime.datetime.combine(self.get_previous_day(current_datetime), datetime.time(23, 59, 59))
else:
current_datetime = datetime.datetime.combine(self.get_next_day(cr, uid, id, current_datetime, context), datetime.time())
current_datetime = datetime.datetime.combine(self.get_next_day(current_datetime), datetime.time())
# avoid infinite loops
iterations += 1
return intervals
def schedule_hours_get_date(self, cr, uid, id, hours, day_dt=None,
@api.multi
def schedule_hours_get_date(self, hours, day_dt=None,
compute_leaves=False, resource_id=None,
default_interval=None, context=None):
default_interval=None):
""" Wrapper on _schedule_hours: return the beginning/ending datetime of
an hours scheduling. """
res = self._schedule_hours(cr, uid, id, hours, day_dt, compute_leaves, resource_id, default_interval, context)
res = self._schedule_hours(hours, day_dt, compute_leaves, resource_id, default_interval)
return res and res[0][0] or False
def schedule_hours(self, cr, uid, id, hours, day_dt=None,
@api.multi
def schedule_hours(self, hours, day_dt=None,
compute_leaves=False, resource_id=None,
default_interval=None, context=None):
default_interval=None):
""" Wrapper on _schedule_hours: return the working intervals of an hours
scheduling. """
return self._schedule_hours(cr, uid, id, hours, day_dt, compute_leaves, resource_id, default_interval, context)
return self._schedule_hours(hours, day_dt, compute_leaves, resource_id, default_interval)
# --------------------------------------------------
# Days scheduling
# --------------------------------------------------
def _schedule_days(self, cr, uid, id, days, day_date=None, compute_leaves=False,
resource_id=None, default_interval=None, context=None):
@api.multi
def _schedule_days(self, days, day_date=None, compute_leaves=False,
resource_id=None, default_interval=None):
"""Schedule days of work, using a calendar and an optional resource to
compute working and leave days. This method can be used backwards, i.e.
scheduling days before a deadline.
@@ -536,157 +529,165 @@ class resource_calendar(osv.osv):
while planned_days < days and iterations < 100:
working_intervals = self.get_working_intervals_of_day(
cr, uid, id, current_datetime,
current_datetime,
compute_leaves=compute_leaves, resource_id=resource_id,
default_interval=default_interval,
context=context)
if id is None or working_intervals: # no calendar -> no working hours, but day is considered as worked
default_interval=default_interval)
if not self or working_intervals: # no calendar -> no working hours, but day is considered as worked
planned_days += 1
intervals += working_intervals
# get next day
if backwards:
current_datetime = self.get_previous_day(cr, uid, id, current_datetime, context)
current_datetime = self.get_previous_day(current_datetime)
else:
current_datetime = self.get_next_day(cr, uid, id, current_datetime, context)
current_datetime = self.get_next_day(current_datetime)
# avoid infinite loops
iterations += 1
return intervals
def schedule_days_get_date(self, cr, uid, id, days, day_date=None, compute_leaves=False,
resource_id=None, default_interval=None, context=None):
@api.multi
def schedule_days_get_date(self, days, day_date=None, compute_leaves=False,
resource_id=None, default_interval=None):
""" Wrapper on _schedule_days: return the beginning/ending datetime of
a days scheduling. """
res = self._schedule_days(cr, uid, id, days, day_date, compute_leaves, resource_id, default_interval, context)
res = self._schedule_days(days, day_date, compute_leaves, resource_id, default_interval)
return res and res[-1][1] or False
def schedule_days(self, cr, uid, id, days, day_date=None, compute_leaves=False,
resource_id=None, default_interval=None, context=None):
@api.multi
def schedule_days(self, days, day_date=None, compute_leaves=False,
resource_id=None, default_interval=None):
""" Wrapper on _schedule_days: return the working intervals of a days
scheduling. """
return self._schedule_days(cr, uid, id, days, day_date, compute_leaves, resource_id, default_interval, context)
return self._schedule_days(days, day_date, compute_leaves, resource_id, default_interval)
# --------------------------------------------------
# Compatibility / to clean / to remove
# --------------------------------------------------
def working_hours_on_day(self, cr, uid, resource_calendar_id, day, context=None):
@api.multi
def working_hours_on_day(self, day):
""" Used in hr_payroll/hr_payroll.py
:deprecated: OpenERP saas-3. Use get_working_hours_of_date instead. Note:
: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(cr, uid, resource_calendar_id.id, start_dt=day, context=None)
return self.get_working_hours_of_date(start_dt=day)
def interval_min_get(self, cr, uid, id, dt_from, hours, resource=False):
@api.multi
def interval_min_get(self, dt_from, hours, resource=False):
""" Schedule hours backwards. Used in mrp_operations/mrp_operations.py.
:deprecated: OpenERP saas-3. Use schedule_hours instead. Note: since
:deprecated: Odoo saas-3. Use schedule_hours instead. Note: since
saas-3, counts leave hours instead of all-day leaves."""
return self.schedule_hours(
cr, uid, id, hours * -1.0,
hours * -1.0,
day_dt=dt_from.replace(minute=0, second=0),
compute_leaves=True, resource_id=resource,
default_interval=(8, 16)
)
def interval_get_multi(self, cr, uid, date_and_hours_by_cal, resource=False, byday=True):
@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: OpenERP saas-3. Use schedule_hours instead. Note:
: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.schedule_hours(
cr, uid, calendar_id, hours,
day_dt=datetime.datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S').replace(second=0),
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,
default_interval=(8, 16)
)
res[(dt_str, hours, calendar_id)] = result
return res
def interval_get(self, cr, uid, id, dt_from, hours, resource=False, byday=True):
@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: OpenERP saas-3. Use get_working_hours instead."""
:deprecated: Odoo saas-3. Use get_working_hours instead."""
self.ensure_one()
res = self.interval_get_multi(
cr, uid, [(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)], resource, byday)[(dt_from.strftime('%Y-%m-%d %H:%M:%S'), hours, id)]
[(fields.Datetime.to_string(dt_from), hours, self.id)], resource, byday)[(fields.Datetime.to_string(dt_from), hours, self.id)]
return res
def interval_hours_get(self, cr, uid, id, dt_from, dt_to, resource=False):
@api.multi
def interval_hours_get(self, dt_from, dt_to, resource=False):
""" Unused wrapper.
:deprecated: OpenERP saas-3. Use get_working_hours instead."""
return self._interval_hours_get(cr, uid, id, dt_from, dt_to, resource_id=resource)
:deprecated: Odoo saas-3. Use get_working_hours instead."""
return self._interval_hours_get(dt_from, dt_to, resource_id=resource)
def _interval_hours_get(self, cr, uid, id, dt_from, dt_to, resource_id=False, timezone_from_uid=None, exclude_leaves=True, context=None):
""" Computes working hours between two dates, taking always same hour/minutes.
:deprecated: OpenERP saas-3. Use get_working_hours instead. Note: since saas-3,
@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(
cr, uid, id, dt_from, dt_to,
dt_from, dt_to,
compute_leaves=(not exclude_leaves), resource_id=resource_id,
default_interval=(8, 16), context=context)
default_interval=(8, 16))
class resource_calendar_attendance(osv.osv):
class ResourceCalendarAttendance(models.Model):
_name = "resource.calendar.attendance"
_description = "Work Detail"
_columns = {
'name' : fields.char("Name", required=True),
'dayofweek': fields.selection([('0','Monday'),('1','Tuesday'),('2','Wednesday'),('3','Thursday'),('4','Friday'),('5','Saturday'),('6','Sunday')], 'Day of Week', required=True, select=True),
'date_from' : fields.date('Starting Date'),
'date_to': fields.date('End Date'),
'hour_from' : fields.float('Work from', required=True, help="Start and End time of working.", select=True),
'hour_to' : fields.float("Work to", required=True),
'calendar_id' : fields.many2one("resource.calendar", "Resource's Calendar", required=True),
}
_order = 'dayofweek, hour_from'
_defaults = {
'dayofweek' : '0'
}
name = fields.Char(required=True)
dayofweek = fields.Selection([
('0', 'Monday'),
('1', 'Tuesday'),
('2', 'Wednesday'),
('3', 'Thursday'),
('4', 'Friday'),
('5', 'Saturday'),
('6', 'Sunday')
], 'Day of Week', required=True, index=True, default='0')
date_from = fields.Date(string='Starting Date')
date_to = fields.Date(string='End Date')
hour_from = fields.Float(string='Work from', required=True, index=True, help="Start and End time of working.")
hour_to = fields.Float(string='Work to', required=True)
calendar_id = fields.Many2one("resource.calendar", string="Resource's Calendar", required=True)
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 resource_resource(osv.osv):
class ResourceResource(models.Model):
_name = "resource.resource"
_description = "Resource Detail"
_columns = {
'name': fields.char("Name", required=True),
'code': fields.char('Code', size=16, copy=False),
'active' : fields.boolean('Active', track_visibility='onchange',
help="If the active field is set to False, it will allow you to hide the resource record without removing it."),
'company_id' : fields.many2one('res.company', 'Company'),
'resource_type': fields.selection([('user','Human'),('material','Material')], 'Resource Type', required=True),
'user_id' : fields.many2one('res.users', 'User', help='Related user name for the resource to manage its access.'),
'time_efficiency' : fields.float('Efficiency Factor', size=8, required=True, help="An efficiency of 50% means the resource is two times smaller than his usual speed."),
'calendar_id' : fields.many2one("resource.calendar", "Working Time", help="Define the schedule of resource"),
}
_defaults = {
'resource_type' : 'user',
'time_efficiency' : 100,
'active' : True,
'company_id': lambda self, cr, uid, context: self.pool.get('res.company')._company_default_get(cr, uid, 'resource.resource', context=context)
}
name = fields.Char(required=True)
code = fields.Char(copy=False)
active = fields.Boolean(track_visibility='onchange', default=True,
help="If the active field is set to False, it will allow you to hide the resource record without removing it.")
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env['res.company']._company_default_get())
resource_type = fields.Selection([
('user', 'Human'),
('material', 'Material')
], string='Resource Type', required=True, default='user')
user_id = fields.Many2one('res.users', string='User', help='Related user name for the resource to manage its access.')
time_efficiency = fields.Float(string='Efficiency Factor', required=True, default=100,
help="This field depict the efficiency of the resource to complete tasks. e.g resource put alone on a phase of 5 days with 5 tasks assigned to him, will show a load of 100% for this phase by default, but if we put a efficiency of 200%, then his load will only be 50%.")
calendar_id = fields.Many2one("resource.calendar", string='Working Time', help="Define the schedule of resource")
def copy(self, cr, uid, id, default=None, context=None):
@api.multi
def copy(self, default=None):
self.ensure_one()
if default is None:
default = {}
if not default.get('name', False):
default.update(name=_('%s (copy)') % (self.browse(cr, uid, id, context=context).name))
return super(resource_resource, self).copy(cr, uid, id, default, context)
if not default.get('name'):
default.update(name=_('%s (copy)') % (self.name))
return super(ResourceResource, self).copy(default)
def _is_work_day(self, date):
""" Whether the provided date is a work day for the subject resource.
@@ -719,37 +720,28 @@ class resource_resource(osv.osv):
if intervals and intervals[0]:
yield dt.date()
class resource_calendar_leaves(osv.osv):
class ResourceCalendarLeaves(models.Model):
_name = "resource.calendar.leaves"
_description = "Leave Detail"
_columns = {
'name' : fields.char("Name"),
'company_id' : fields.related('calendar_id','company_id',type='many2one',relation='res.company',string="Company", store=True, readonly=True),
'calendar_id' : fields.many2one("resource.calendar", "Working Time"),
'date_from' : fields.datetime('Start Date', required=True),
'date_to' : fields.datetime('End Date', required=True),
'resource_id' : fields.many2one("resource.resource", "Resource", help="If empty, this is a generic holiday for the company. If a resource is set, the holiday/leave is only for this resource"),
}
def check_dates(self, cr, uid, ids, context=None):
for leave in self.browse(cr, uid, ids, context=context):
if leave.date_from and leave.date_to and leave.date_from > leave.date_to:
return False
return True
name = fields.Char()
company_id = fields.Many2one('res.company', related='calendar_id.company_id', string="Company", store=True, readonly=True)
calendar_id = fields.Many2one('resource.calendar', string='Working Time')
date_from = fields.Datetime(string='Start Date', required=True)
date_to = fields.Datetime(string='End Date', required=True)
resource_id = fields.Many2one("resource.resource", string='Resource',
help="If empty, this is a generic holiday for the company. If a resource is set, the holiday/leave is only for this resource")
_constraints = [
(check_dates, 'Error! leave start-date must be lower then leave end-date.', ['date_from', 'date_to'])
]
@api.constrains('date_from', 'date_to')
def check_dates(self):
if self.filtered(lambda leave: leave.date_from > leave.date_to):
raise ValidationError(_('Error! leave start-date must be lower then leave end-date.'))
def onchange_resource(self, cr, uid, ids, resource, context=None):
result = {}
if resource:
resource_pool = self.pool.get('resource.resource')
result['calendar_id'] = resource_pool.browse(cr, uid, resource, context=context).calendar_id.id
return {'value': result}
return {'value': {'calendar_id': []}}
@api.onchange('resource_id')
def onchange_resource(self):
self.calendar_id = self.resource_id.calendar_id
def seconds(td):
assert isinstance(td, datetime.timedelta)
assert isinstance(td, timedelta)
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10.**6
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<odoo>
<data noupdate="1">
<record model="ir.rule" id="resource_own_leaves">
@@ -13,4 +13,4 @@
</record>
</data>
</openerp>
</odoo>
@@ -1,6 +0,0 @@
-
I duplicate the resource "Analyst"
-
!python {model: resource.resource}: |
copied_id = self.copy(cr, uid, ref("resource_analyst"))
assert copied_id, "Unable to Duplicate Resource"
-53
View File
@@ -1,53 +0,0 @@
-
In order to test resource.
-
I assign working calendar '45 Hours/Week' to human resource.
-
!python {model: resource.resource}: |
self.write(cr, uid, [ref('resource_analyst'), ref('resource_designer'), ref('resource_developer')], {'calendar_id' : ref('timesheet_group1'), 'resource_type': 'user'})
-
I had Project of OpenERP Integration of 50 Hours with three human resource assigned on it. I have started project from this week start.
-
I check per day work hour availability of the Resource based on Working Calendar Assigned to each resource, for first day of the week.
-
!python {model: resource.resource}: |
from openerp.tools import float_compare
calendar_pool = self.pool.get('resource.calendar')
resources = self.browse(cr, uid, [ref('resource_analyst'), ref('resource_designer'), ref('resource_developer')], context)
from datetime import datetime, timedelta
now = datetime.now()
dt = now - timedelta(days=now.weekday())
for resource in resources:
result = calendar_pool.working_hours_on_day(cr, uid, resource.calendar_id, dt, context)
assert float_compare(result, 8.0, precision_digits=2) == 0, 'Wrong calculation of day work hour availability of the Resource (found %d).' % result
-
Now, resource "Developer" drafted leave on Thursday in this week.
-
!python {model: resource.calendar.leaves}: |
from datetime import datetime,timedelta
now = datetime.now()
dt = (now - timedelta(days=now.weekday()) ) + timedelta(days=3)
self.write(cr, uid, [ref('resource_dummyleave')], {'resource_id': ref('resource_developer'), 'calendar_id': ref('timesheet_group1'), 'date_from': dt.strftime("%Y-%m-%d 09:00:00"), 'date_to': dt.strftime("%Y-%m-%d 18:00:00")})
-
I check Actual working hours on resource 'Developer' from this week
-
!python {model: resource.calendar}: |
from datetime import datetime
from dateutil.relativedelta import relativedelta
now = datetime.now()
dt_from = now - relativedelta(days=now.weekday(), hour=8, minute=30)
dt_to = dt_from + relativedelta(days=6, hour=17)
hours = self.interval_hours_get(cr, uid, ref('timesheet_group1'), dt_from, dt_to, resource=ref('resource_developer'))
assert hours > 27 , 'Invalid Total Week working hour calculated, got %r, expected > 27' % hours
-
Project Analysis work is of 20 hours which will start from Week start so i will calculate working schedule for resource Analyst for the same.
-
!python {model: resource.calendar}: |
from datetime import datetime, timedelta
now = datetime.now()
work_intreval = self.interval_min_get(cr, uid, ref('timesheet_group1'), now, 20.0, resource=ref('resource_designer'))
assert len(work_intreval) >= 5, 'Wrong Schedule Calculated'
+54 -58
View File
@@ -1,106 +1,102 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
from openerp.tests import common
from odoo.fields import Datetime
from odoo.tests.common import TransactionCase
class TestResourceCommon(common.TransactionCase):
class TestResourceCommon(TransactionCase):
def setUp(self):
super(TestResourceCommon, self).setUp()
cr, uid = self.cr, self.uid
self.context = context = dict(tz='UTC')
self.registry('res.users').write(cr, uid, uid, {'tz': 'UTC'}, context=context)
self.env['res.users'].browse(self.env.uid).with_context(context).write({'tz': 'UTC'})
# Usefull models
self.resource_resource = self.registry('resource.resource')
self.resource_calendar = self.registry('resource.calendar')
self.resource_attendance = self.registry('resource.calendar.attendance')
self.resource_leaves = self.registry('resource.calendar.leaves')
self.Resource = self.env['resource.resource']
self.ResourceCalendar = self.env['resource.calendar']
self.ResourceAttendance = self.env['resource.calendar.attendance']
self.ResourceLeaves = self.env['resource.calendar.leaves']
# Some demo data
self.date1 = datetime.strptime('2013-02-12 09:08:07', '%Y-%m-%d %H:%M:%S') # weekday() returns 1, isoweekday() returns 2
self.date2 = datetime.strptime('2013-02-15 10:11:12', '%Y-%m-%d %H:%M:%S') # weekday() returns 4, isoweekday() returns 5
self.date1 = Datetime.from_string('2013-02-12 09:08:07') # weekday() returns 1, isoweekday() returns 2
self.date2 = Datetime.from_string('2013-02-15 10:11:12') # weekday() returns 4, isoweekday() returns 5
# Leave1: 19/02/2013, from 9 to 12, is a day 1
self.leave1_start = datetime.strptime('2013-02-19 09:00:00', '%Y-%m-%d %H:%M:%S')
self.leave1_end = datetime.strptime('2013-02-19 12:00:00', '%Y-%m-%d %H:%M:%S')
self.leave1_start = Datetime.from_string('2013-02-19 09:00:00')
self.leave1_end = Datetime.from_string('2013-02-19 12:00:00')
# Leave2: 22/02/2013, from 9 to 15, is a day 4
self.leave2_start = datetime.strptime('2013-02-22 09:00:00', '%Y-%m-%d %H:%M:%S')
self.leave2_end = datetime.strptime('2013-02-22 15:00:00', '%Y-%m-%d %H:%M:%S')
self.leave2_start = Datetime.from_string('2013-02-22 09:00:00')
self.leave2_end = Datetime.from_string('2013-02-22 15:00:00')
# Leave3: 25/02/2013 (day0) -> 01/03/2013 (day4)
self.leave3_start = datetime.strptime('2013-02-25 13:00:00', '%Y-%m-%d %H:%M:%S')
self.leave3_end = datetime.strptime('2013-03-01 11:30:00', '%Y-%m-%d %H:%M:%S')
self.leave3_start = Datetime.from_string('2013-02-25 13:00:00')
self.leave3_end = Datetime.from_string('2013-03-01 11:30:00')
# Resource data
# Calendar working days: 1 (8-16 -> 8hours), 4 (8-13, 16-23 -> 12hours)
self.calendar_id = self.resource_calendar.create(
cr, uid, {
self.calendar = self.ResourceCalendar.with_context(context).create(
{
'name': 'TestCalendar',
}, context=context
}
)
self.att1_id = self.resource_attendance.create(
cr, uid, {
self.att1_id = self.ResourceAttendance.with_context(context).create(
{
'name': 'Att1',
'dayofweek': '1',
'hour_from': 8,
'hour_to': 16,
'calendar_id': self.calendar_id,
}, context=context
)
self.att2_id = self.resource_attendance.create(
cr, uid, {
'calendar_id': self.calendar.id,
}
).id
self.att2_id = self.ResourceAttendance.with_context(context).create(
{
'name': 'Att2',
'dayofweek': '4',
'hour_from': 8,
'hour_to': 13,
'calendar_id': self.calendar_id,
}, context=context
)
self.att3_id = self.resource_attendance.create(
cr, uid, {
'calendar_id': self.calendar.id,
}
).id
self.att3_id = self.ResourceAttendance.with_context(context).create(
{
'name': 'Att3',
'dayofweek': '4',
'hour_from': 16,
'hour_to': 23,
'calendar_id': self.calendar_id,
}, context=context
)
self.resource1_id = self.resource_resource.create(
cr, uid, {
'calendar_id': self.calendar.id,
}
).id
self.resource1_id = self.Resource.with_context(context).create(
{
'name': 'TestResource1',
'resource_type': 'user',
'time_efficiency': 150.0,
'calendar_id': self.calendar_id,
}, context=context
)
self.leave1_id = self.resource_leaves.create(
cr, uid, {
'calendar_id': self.calendar.id,
}
).id
self.leave1_id = self.ResourceLeaves.with_context(context).create(
{
'name': 'GenericLeave',
'calendar_id': self.calendar_id,
'calendar_id': self.calendar.id,
'date_from': self.leave1_start,
'date_to': self.leave1_end,
}, context=context
)
self.leave2_id = self.resource_leaves.create(
cr, uid, {
}
).id
self.leave2_id = self.ResourceLeaves.with_context(context).create(
{
'name': 'ResourceLeave',
'calendar_id': self.calendar_id,
'calendar_id': self.calendar.id,
'resource_id': self.resource1_id,
'date_from': self.leave2_start,
'date_to': self.leave2_end,
}, context=context
)
self.leave3_id = self.resource_leaves.create(
cr, uid, {
}
).id
self.leave3_id = self.ResourceLeaves.with_context(context).create(
{
'name': 'ResourceLeave2',
'calendar_id': self.calendar_id,
'calendar_id': self.calendar.id,
'resource_id': self.resource1_id,
'date_from': self.leave3_start,
'date_to': self.leave3_end,
}, context=context
)
# Some browse data
self.calendar = self.resource_calendar.browse(cr, uid, self.calendar_id, context=context)
}
).id
+221 -253
View File
@@ -6,7 +6,9 @@ from datetime import datetime, timedelta, date
import babel.dates
from dateutil.relativedelta import relativedelta
from openerp.addons.resource.tests.common import TestResourceCommon
from odoo.fields import Datetime
from odoo.tools import float_compare
from odoo.addons.resource.tests.common import TestResourceCommon
from openerp.tests import TransactionCase
@@ -14,93 +16,91 @@ from openerp.tests import TransactionCase
class TestResource(TestResourceCommon):
def test_00_intervals(self):
cr, uid = self.cr, self.uid
intervals = [
(
datetime.strptime('2013-02-04 09:00:00', '%Y-%m-%d %H:%M:%S'),
datetime.strptime('2013-02-04 11:00:00', '%Y-%m-%d %H:%M:%S')
Datetime.from_string('2013-02-04 09:00:00'),
Datetime.from_string('2013-02-04 11:00:00')
), (
datetime.strptime('2013-02-04 08:00:00', '%Y-%m-%d %H:%M:%S'),
datetime.strptime('2013-02-04 12:00:00', '%Y-%m-%d %H:%M:%S')
Datetime.from_string('2013-02-04 08:00:00'),
Datetime.from_string('2013-02-04 12:00:00')
), (
datetime.strptime('2013-02-04 11:00:00', '%Y-%m-%d %H:%M:%S'),
datetime.strptime('2013-02-04 14:00:00', '%Y-%m-%d %H:%M:%S')
Datetime.from_string('2013-02-04 11:00:00'),
Datetime.from_string('2013-02-04 14:00:00')
), (
datetime.strptime('2013-02-04 17:00:00', '%Y-%m-%d %H:%M:%S'),
datetime.strptime('2013-02-04 21:00:00', '%Y-%m-%d %H:%M:%S')
Datetime.from_string('2013-02-04 17:00:00'),
Datetime.from_string('2013-02-04 21:00:00')
), (
datetime.strptime('2013-02-03 08:00:00', '%Y-%m-%d %H:%M:%S'),
datetime.strptime('2013-02-03 10:00:00', '%Y-%m-%d %H:%M:%S')
Datetime.from_string('2013-02-03 08:00:00'),
Datetime.from_string('2013-02-03 10:00:00')
), (
datetime.strptime('2013-02-04 18:00:00', '%Y-%m-%d %H:%M:%S'),
datetime.strptime('2013-02-04 19:00:00', '%Y-%m-%d %H:%M:%S')
Datetime.from_string('2013-02-04 18:00:00'),
Datetime.from_string('2013-02-04 19:00:00')
)
]
# Test: interval cleaning
cleaned_intervals = self.resource_calendar.interval_clean(intervals)
cleaned_intervals = self.ResourceCalendar.interval_clean(intervals)
self.assertEqual(len(cleaned_intervals), 3, 'resource_calendar: wrong interval cleaning')
# First interval: 03, unchanged
self.assertEqual(cleaned_intervals[0][0], datetime.strptime('2013-02-03 08:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[0][1], datetime.strptime('2013-02-03 10:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[0][0], Datetime.from_string('2013-02-03 08:00:00'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[0][1], Datetime.from_string('2013-02-03 10:00:00'), 'resource_calendar: wrong interval cleaning')
# Second intreval: 04, 08-14, combining 08-12 and 11-14, 09-11 being inside 08-12
self.assertEqual(cleaned_intervals[1][0], datetime.strptime('2013-02-04 08:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[1][1], datetime.strptime('2013-02-04 14:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[1][0], Datetime.from_string('2013-02-04 08:00:00'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[1][1], Datetime.from_string('2013-02-04 14:00:00'), 'resource_calendar: wrong interval cleaning')
# Third interval: 04, 17-21, 18-19 being inside 17-21
self.assertEqual(cleaned_intervals[2][0], datetime.strptime('2013-02-04 17:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[2][1], datetime.strptime('2013-02-04 21:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[2][0], Datetime.from_string('2013-02-04 17:00:00'), 'resource_calendar: wrong interval cleaning')
self.assertEqual(cleaned_intervals[2][1], Datetime.from_string('2013-02-04 21:00:00'), 'resource_calendar: wrong interval cleaning')
# Test: disjoint removal
working_interval = (datetime.strptime('2013-02-04 08:00:00', '%Y-%m-%d %H:%M:%S'), datetime.strptime('2013-02-04 18:00:00', '%Y-%m-%d %H:%M:%S'))
result = self.resource_calendar.interval_remove_leaves(cr, uid, working_interval, intervals)
working_interval = (Datetime.from_string('2013-02-04 08:00:00'), Datetime.from_string('2013-02-04 18:00:00'))
result = self.ResourceCalendar.interval_remove_leaves(working_interval, intervals)
self.assertEqual(len(result), 1, 'resource_calendar: wrong leave removal from interval')
# First interval: 04, 14-17
self.assertEqual(result[0][0], datetime.strptime('2013-02-04 14:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][1], datetime.strptime('2013-02-04 17:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][0], Datetime.from_string('2013-02-04 14:00:00'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][1], Datetime.from_string('2013-02-04 17:00:00'), 'resource_calendar: wrong leave removal from interval')
# Test: schedule hours on intervals
result = self.resource_calendar.interval_schedule_hours(cleaned_intervals, 5.5)
result = self.ResourceCalendar.interval_schedule_hours(cleaned_intervals, 5.5)
self.assertEqual(len(result), 2, 'resource_calendar: wrong hours scheduling in interval')
# First interval: 03, 8-10 untouches
self.assertEqual(result[0][0], datetime.strptime('2013-02-03 08:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][1], datetime.strptime('2013-02-03 10:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][0], Datetime.from_string('2013-02-03 08:00:00'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][1], Datetime.from_string('2013-02-03 10:00:00'), 'resource_calendar: wrong leave removal from interval')
# First interval: 04, 08-11:30
self.assertEqual(result[1][0], datetime.strptime('2013-02-04 08:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[1][1], datetime.strptime('2013-02-04 11:30:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[1][0], Datetime.from_string('2013-02-04 08:00:00'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[1][1], Datetime.from_string('2013-02-04 11:30:00'), 'resource_calendar: wrong leave removal from interval')
# Test: schedule hours on intervals, backwards
cleaned_intervals.reverse()
result = self.resource_calendar.interval_schedule_hours(cleaned_intervals, 5.5, remove_at_end=False)
result = self.ResourceCalendar._model.interval_schedule_hours(cleaned_intervals, 5.5, remove_at_end=False)
self.assertEqual(len(result), 2, 'resource_calendar: wrong hours scheduling in interval')
# First interval: 03, 8-10 untouches
self.assertEqual(result[0][0], datetime.strptime('2013-02-04 17:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][1], datetime.strptime('2013-02-04 21:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][0], Datetime.from_string('2013-02-04 17:00:00'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[0][1], Datetime.from_string('2013-02-04 21:00:00'), 'resource_calendar: wrong leave removal from interval')
# First interval: 04, 08-11:30
self.assertEqual(result[1][0], datetime.strptime('2013-02-04 12:30:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[1][1], datetime.strptime('2013-02-04 14:00:00', '%Y-%m-%d %H:%M:%S'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[1][0], Datetime.from_string('2013-02-04 12:30:00'), 'resource_calendar: wrong leave removal from interval')
self.assertEqual(result[1][1], Datetime.from_string('2013-02-04 14:00:00'), 'resource_calendar: wrong leave removal from interval')
def test_10_calendar_basics(self):
""" Testing basic method of resource.calendar """
cr, uid = self.cr, self.uid
# --------------------------------------------------
# Test1: get_next_day
# --------------------------------------------------
# Test: next day: next day after day1 is day4
date = self.resource_calendar.get_next_day(cr, uid, self.calendar_id, day_date=self.date1.date())
date = self.calendar.get_next_day(day_date=self.date1.date())
self.assertEqual(date, self.date2.date(), 'resource_calendar: wrong next day computing')
# Test: next day: next day after day4 is (day1+7)
date = self.resource_calendar.get_next_day(cr, uid, self.calendar_id, day_date=self.date2.date())
date = self.calendar.get_next_day(day_date=self.date2.date())
self.assertEqual(date, self.date1.date() + relativedelta(days=7), 'resource_calendar: wrong next day computing')
# Test: next day: next day after day4+1 is (day1+7)
date = self.resource_calendar.get_next_day(cr, uid, self.calendar_id, day_date=self.date2.date() + relativedelta(days=1))
date = self.calendar.get_next_day(day_date=self.date2.date() + relativedelta(days=1))
self.assertEqual(date, self.date1.date() + relativedelta(days=7), 'resource_calendar: wrong next day computing')
# Test: next day: next day after day1-1 is day1
date = self.resource_calendar.get_next_day(cr, uid, self.calendar_id, day_date=self.date1.date() + relativedelta(days=-1))
date = self.calendar.get_next_day(day_date=self.date1.date() + relativedelta(days=-1))
self.assertEqual(date, self.date1.date(), 'resource_calendar: wrong next day computing')
# --------------------------------------------------
@@ -108,174 +108,134 @@ class TestResource(TestResourceCommon):
# --------------------------------------------------
# Test: previous day: previous day before day1 is (day4-7)
date = self.resource_calendar.get_previous_day(cr, uid, self.calendar_id, day_date=self.date1.date())
date = self.calendar.get_previous_day(day_date=self.date1.date())
self.assertEqual(date, self.date2.date() + relativedelta(days=-7), 'resource_calendar: wrong previous day computing')
# Test: previous day: previous day before day4 is day1
date = self.resource_calendar.get_previous_day(cr, uid, self.calendar_id, day_date=self.date2.date())
date = self.calendar.get_previous_day(day_date=self.date2.date())
self.assertEqual(date, self.date1.date(), 'resource_calendar: wrong previous day computing')
# Test: previous day: previous day before day4+1 is day4
date = self.resource_calendar.get_previous_day(cr, uid, self.calendar_id, day_date=self.date2.date() + relativedelta(days=1))
date = self.calendar.get_previous_day(day_date=self.date2.date() + relativedelta(days=1))
self.assertEqual(date, self.date2.date(), 'resource_calendar: wrong previous day computing')
# Test: previous day: previous day before day1-1 is (day4-7)
date = self.resource_calendar.get_previous_day(cr, uid, self.calendar_id, day_date=self.date1.date() + relativedelta(days=-1))
date = self.calendar.get_previous_day(day_date=self.date1.date() + relativedelta(days=-1))
self.assertEqual(date, self.date2.date() + relativedelta(days=-7), 'resource_calendar: wrong previous day computing')
# --------------------------------------------------
# Test3: misc
# --------------------------------------------------
weekdays = self.resource_calendar.get_weekdays(cr, uid, self.calendar_id)
weekdays = self.calendar.get_weekdays()
self.assertEqual(weekdays, [1, 4], 'resource_calendar: wrong weekdays computing')
# attendances = self.resource_calendar.get_attendances_for_weekdays(cr, uid, self.calendar_id, [2, 3, 4, 5])
# self.assertEqual(set([att.id for att in attendances]), set([self.att2_id, self.att3_id]),
# 'resource_calendar: wrong attendances filtering by weekdays computing')
def test_20_calendar_working_intervals(self):
""" Testing working intervals computing method of resource.calendar """
cr, uid = self.cr, self.uid
context = self.context
_format = '%Y-%m-%d %H:%M:%S'
# Test: day0 without leaves: 1 interval
intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1, context=context)
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date1)
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-12 09:08:07', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-12 09:08:07'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-12 16:00:00'), 'resource_calendar: wrong working intervals')
# Test: day3 without leaves: 2 interval
intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date2, context=context)
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date2)
self.assertEqual(len(intervals), 2, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-15 10:11:12', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-15 13:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][0], datetime.strptime('2013-02-15 16:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][1], datetime.strptime('2013-02-15 23:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-15 10:11:12'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-15 13:00:00'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][0], Datetime.from_string('2013-02-15 16:00:00'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][1], Datetime.from_string('2013-02-15 23:00:00'), 'resource_calendar: wrong working intervals')
# Test: day0 with leaves outside range: 1 interval
intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=0), compute_leaves=True, context=context)
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date1.replace(hour=0), compute_leaves=True)
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-12 08:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-12 08:00:00'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-12 16:00:00'), 'resource_calendar: wrong working intervals')
# Test: day0 with leaves: 2 intervals because of leave between 9 ans 12, ending at 15:45:30
intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id,
start_dt=self.date1.replace(hour=8) + relativedelta(days=7),
end_dt=self.date1.replace(hour=15, minute=45, second=30) + relativedelta(days=7),
compute_leaves=True, context=context)
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date1.replace(hour=8) + relativedelta(days=7),
end_dt=self.date1.replace(hour=15, minute=45, second=30) + relativedelta(days=7),
compute_leaves=True)
self.assertEqual(len(intervals), 2, 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-19 08:08:07', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-19 09:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][0], datetime.strptime('2013-02-19 12:00:00', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][1], datetime.strptime('2013-02-19 15:45:30', _format), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-19 08:08:07'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-19 09:00:00'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][0], Datetime.from_string('2013-02-19 12:00:00'), 'resource_calendar: wrong working intervals')
self.assertEqual(intervals[1][1], Datetime.from_string('2013-02-19 15:45:30'), 'resource_calendar: wrong working intervals')
def test_30_calendar_working_days(self):
""" Testing calendar hours computation on a working day """
cr, uid = self.cr, self.uid
context = self.context
_format = '%Y-%m-%d %H:%M:%S'
# Test: day1, beginning at 10:30 -> work from 10:30 (arrival) until 16:00
intervals = self.resource_calendar.get_working_intervals_of_day(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=10, minute=30, second=0), context=context)
intervals = self.calendar.get_working_intervals_of_day(start_dt=self.date1.replace(hour=10, minute=30, second=0))
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-12 10:30:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-12 10:30:00'), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-12 16:00:00'), 'resource_calendar: wrong working interval / day computing')
# Test: hour computation for same interval, should give 5.5
wh = self.resource_calendar.get_working_hours_of_date(cr, uid, self.calendar_id, start_dt=self.date1.replace(hour=10, minute=30, second=0), context=context)
wh = self.calendar.get_working_hours_of_date(start_dt=self.date1.replace(hour=10, minute=30, second=0))
self.assertEqual(wh, 5.5, 'resource_calendar: wrong working interval / day time computing')
# Test: day1+7 on leave, without leave computation
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=7), context=context
intervals = self.calendar.get_working_intervals_of_day(
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=7)
)
# Result: day1 (08->16)
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working interval/day computing')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-19 08:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-19 16:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-19 08:00:00'), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-19 16:00:00'), 'resource_calendar: wrong working interval / day computing')
# Test: day1+7 on leave, with generic leave computation
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
intervals = self.calendar.get_working_intervals_of_day(
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=7),
compute_leaves=True, context=context
compute_leaves=True
)
# Result: day1 (08->09 + 12->16)
self.assertEqual(len(intervals), 2, 'resource_calendar: wrong working interval/day computing')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-19 08:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-19 09:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[1][0], datetime.strptime('2013-02-19 12:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[1][1], datetime.strptime('2013-02-19 16:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-19 08:00:00'), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-19 09:00:00'), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[1][0], Datetime.from_string('2013-02-19 12:00:00'), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[1][1], Datetime.from_string('2013-02-19 16:00:00'), 'resource_calendar: wrong working interval / day computing')
# Test: day1+14 on leave, with generic leave computation
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
intervals = self.calendar.get_working_intervals_of_day(
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=14),
compute_leaves=True, context=context
compute_leaves=True
)
# Result: day1 (08->16)
self.assertEqual(len(intervals), 1, 'resource_calendar: wrong working interval/day computing')
self.assertEqual(intervals[0][0], datetime.strptime('2013-02-26 08:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], datetime.strptime('2013-02-26 16:00:00', _format), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][0], Datetime.from_string('2013-02-26 08:00:00'), 'resource_calendar: wrong working interval / day computing')
self.assertEqual(intervals[0][1], Datetime.from_string('2013-02-26 16:00:00'), 'resource_calendar: wrong working interval / day computing')
# Test: day1+14 on leave, with resource leave computation
intervals = self.resource_calendar.get_working_intervals_of_day(
cr, uid, self.calendar_id,
intervals = self.calendar.get_working_intervals_of_day(
start_dt=self.date1.replace(hour=7, minute=0, second=0) + relativedelta(days=14),
compute_leaves=True,
resource_id=self.resource1_id, context=context
resource_id=self.resource1_id
)
# Result: nothing, because on leave
self.assertEqual(len(intervals), 0, 'resource_calendar: wrong working interval/day computing')
def test_40_calendar_hours_scheduling(self):
""" Testing calendar hours scheduling """
cr, uid = self.cr, self.uid
context = self.context
_format = '%Y-%m-%d %H:%M:%S'
# --------------------------------------------------
# Test0: schedule hours backwards (old interval_min_get)
# Done without calendar
# --------------------------------------------------
# Done without calendar
# res = self.resource_calendar.interval_min_get(cr, uid, None, self.date1, 40, resource=False)
# res: (datetime.datetime(2013, 2, 7, 9, 8, 7), datetime.datetime(2013, 2, 12, 9, 8, 7))
# --------------------------------------------------
# Test1: schedule hours backwards (old interval_min_get)
# --------------------------------------------------
# res = self.resource_calendar.interval_min_get(cr, uid, self.calendar_id, self.date1, 40, resource=False)
# (datetime.datetime(2013, 1, 29, 9, 0), datetime.datetime(2013, 1, 29, 16, 0))
# (datetime.datetime(2013, 2, 1, 8, 0), datetime.datetime(2013, 2, 1, 13, 0))
# (datetime.datetime(2013, 2, 1, 16, 0), datetime.datetime(2013, 2, 1, 23, 0))
# (datetime.datetime(2013, 2, 5, 8, 0), datetime.datetime(2013, 2, 5, 16, 0))
# (datetime.datetime(2013, 2, 8, 8, 0), datetime.datetime(2013, 2, 8, 13, 0))
# (datetime.datetime(2013, 2, 8, 16, 0), datetime.datetime(2013, 2, 8, 23, 0))
# (datetime.datetime(2013, 2, 12, 8, 0), datetime.datetime(2013, 2, 12, 9, 0))
res = self.resource_calendar.schedule_hours(cr, uid, self.calendar_id, -40, day_dt=self.date1.replace(minute=0, second=0), context=context)
res = self.calendar.schedule_hours(-40, day_dt=self.date1.replace(minute=0, second=0))
# current day, limited at 09:00 because of day_dt specified -> 1 hour
self.assertEqual(res[-1][0], datetime.strptime('2013-02-12 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-1][1], datetime.strptime('2013-02-12 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-1][0], Datetime.from_string('2013-02-12 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-1][1], Datetime.from_string('2013-02-12 09:00:00'), 'resource_calendar: wrong hours scheduling')
# previous days: 5+7 hours / 8 hours / 5+7 hours -> 32 hours
self.assertEqual(res[-2][0], datetime.strptime('2013-02-08 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-2][1], datetime.strptime('2013-02-08 23:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-3][0], datetime.strptime('2013-02-08 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-3][1], datetime.strptime('2013-02-08 13:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-4][0], datetime.strptime('2013-02-05 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-4][1], datetime.strptime('2013-02-05 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-5][0], datetime.strptime('2013-02-01 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-5][1], datetime.strptime('2013-02-01 23:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-6][0], datetime.strptime('2013-02-01 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-6][1], datetime.strptime('2013-02-01 13:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-2][0], Datetime.from_string('2013-02-08 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-2][1], Datetime.from_string('2013-02-08 23:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-3][0], Datetime.from_string('2013-02-08 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-3][1], Datetime.from_string('2013-02-08 13:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-4][0], Datetime.from_string('2013-02-05 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-4][1], Datetime.from_string('2013-02-05 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-5][0], Datetime.from_string('2013-02-01 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-5][1], Datetime.from_string('2013-02-01 23:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-6][0], Datetime.from_string('2013-02-01 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-6][1], Datetime.from_string('2013-02-01 13:00:00'), 'resource_calendar: wrong hours scheduling')
# 7 hours remaining
self.assertEqual(res[-7][0], datetime.strptime('2013-01-29 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-7][1], datetime.strptime('2013-01-29 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-7][0], Datetime.from_string('2013-01-29 09:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[-7][1], Datetime.from_string('2013-01-29 16:00:00'), 'resource_calendar: wrong hours scheduling')
# Compute scheduled hours
td = timedelta()
for item in res:
@@ -283,74 +243,53 @@ class TestResource(TestResourceCommon):
self.assertEqual(seconds(td) / 3600.0, 40.0, 'resource_calendar: wrong hours scheduling')
# --------------------------------------------------
# Test2: schedule hours forward (old interval_get)
# Test2: schedule hours forward
# --------------------------------------------------
# res = self.resource_calendar.interval_get(cr, uid, self.calendar_id, self.date1, 40, resource=False, byday=True)
# (datetime.datetime(2013, 2, 12, 9, 0), datetime.datetime(2013, 2, 12, 16, 0))
# (datetime.datetime(2013, 2, 15, 8, 0), datetime.datetime(2013, 2, 15, 13, 0))
# (datetime.datetime(2013, 2, 15, 16, 0), datetime.datetime(2013, 2, 15, 23, 0))
# (datetime.datetime(2013, 2, 22, 8, 0), datetime.datetime(2013, 2, 22, 13, 0))
# (datetime.datetime(2013, 2, 22, 16, 0), datetime.datetime(2013, 2, 22, 23, 0))
# (datetime.datetime(2013, 2, 26, 8, 0), datetime.datetime(2013, 2, 26, 16, 0))
# (datetime.datetime(2013, 3, 1, 8, 0), datetime.datetime(2013, 3, 1, 9, 0))
res = self.resource_calendar.schedule_hours(
cr, uid, self.calendar_id, 40,
day_dt=self.date1.replace(minute=0, second=0), context=context
res = self.calendar.schedule_hours(
40, day_dt=self.date1.replace(minute=0, second=0)
)
self.assertEqual(res[0][0], datetime.strptime('2013-02-12 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][0], datetime.strptime('2013-02-15 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][1], datetime.strptime('2013-02-15 13:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][0], datetime.strptime('2013-02-15 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][1], datetime.strptime('2013-02-15 23:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][0], datetime.strptime('2013-02-19 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][1], datetime.strptime('2013-02-19 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][0], datetime.strptime('2013-02-22 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][1], datetime.strptime('2013-02-22 13:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][0], datetime.strptime('2013-02-22 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][1], datetime.strptime('2013-02-22 23:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][0], datetime.strptime('2013-02-26 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][1], datetime.strptime('2013-02-26 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][0], Datetime.from_string('2013-02-12 09:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][1], Datetime.from_string('2013-02-12 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][0], Datetime.from_string('2013-02-15 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][1], Datetime.from_string('2013-02-15 13:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][0], Datetime.from_string('2013-02-15 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][1], Datetime.from_string('2013-02-15 23:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][0], Datetime.from_string('2013-02-19 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][1], Datetime.from_string('2013-02-19 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][0], Datetime.from_string('2013-02-22 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][1], Datetime.from_string('2013-02-22 13:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][0], Datetime.from_string('2013-02-22 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][1], Datetime.from_string('2013-02-22 23:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][0], Datetime.from_string('2013-02-26 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][1], Datetime.from_string('2013-02-26 09:00:00'), 'resource_calendar: wrong hours scheduling')
td = timedelta()
for item in res:
td += item[1] - item[0]
self.assertEqual(seconds(td) / 3600.0, 40.0, 'resource_calendar: wrong hours scheduling')
# res = self.resource_calendar.interval_get(cr, uid, self.calendar_id, self.date1, 40, resource=self.resource1_id, byday=True)
# (datetime.datetime(2013, 2, 12, 9, 0), datetime.datetime(2013, 2, 12, 16, 0))
# (datetime.datetime(2013, 2, 15, 8, 0), datetime.datetime(2013, 2, 15, 13, 0))
# (datetime.datetime(2013, 2, 15, 16, 0), datetime.datetime(2013, 2, 15, 23, 0))
# (datetime.datetime(2013, 3, 1, 8, 0), datetime.datetime(2013, 3, 1, 13, 0))
# (datetime.datetime(2013, 3, 1, 16, 0), datetime.datetime(2013, 3, 1, 23, 0))
# (datetime.datetime(2013, 3, 5, 8, 0), datetime.datetime(2013, 3, 5, 16, 0))
# (datetime.datetime(2013, 3, 8, 8, 0), datetime.datetime(2013, 3, 8, 9, 0))
res = self.resource_calendar.schedule_hours(
cr, uid, self.calendar_id, 40,
day_dt=self.date1.replace(minute=0, second=0),
compute_leaves=True,
resource_id=self.resource1_id, context=context
res = self.calendar.schedule_hours(
40, day_dt=self.date1.replace(minute=0, second=0),
compute_leaves=True, resource_id=self.resource1_id
)
self.assertEqual(res[0][0], datetime.strptime('2013-02-12 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][1], datetime.strptime('2013-02-12 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][0], datetime.strptime('2013-02-15 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][1], datetime.strptime('2013-02-15 13:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][0], datetime.strptime('2013-02-15 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][1], datetime.strptime('2013-02-15 23:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][0], datetime.strptime('2013-02-19 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][1], datetime.strptime('2013-02-19 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][0], datetime.strptime('2013-02-19 12:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][1], datetime.strptime('2013-02-19 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][0], datetime.strptime('2013-02-22 08:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][1], datetime.strptime('2013-02-22 09:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][0], datetime.strptime('2013-02-22 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][1], datetime.strptime('2013-02-22 23:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[7][0], datetime.strptime('2013-03-01 11:30:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[7][1], datetime.strptime('2013-03-01 13:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[8][0], datetime.strptime('2013-03-01 16:00:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[8][1], datetime.strptime('2013-03-01 22:30:00', _format), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][0], Datetime.from_string('2013-02-12 09:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[0][1], Datetime.from_string('2013-02-12 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][0], Datetime.from_string('2013-02-15 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[1][1], Datetime.from_string('2013-02-15 13:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][0], Datetime.from_string('2013-02-15 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[2][1], Datetime.from_string('2013-02-15 23:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][0], Datetime.from_string('2013-02-19 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[3][1], Datetime.from_string('2013-02-19 09:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][0], Datetime.from_string('2013-02-19 12:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[4][1], Datetime.from_string('2013-02-19 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][0], Datetime.from_string('2013-02-22 08:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[5][1], Datetime.from_string('2013-02-22 09:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][0], Datetime.from_string('2013-02-22 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[6][1], Datetime.from_string('2013-02-22 23:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[7][0], Datetime.from_string('2013-03-01 11:30:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[7][1], Datetime.from_string('2013-03-01 13:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[8][0], Datetime.from_string('2013-03-01 16:00:00'), 'resource_calendar: wrong hours scheduling')
self.assertEqual(res[8][1], Datetime.from_string('2013-03-01 22:30:00'), 'resource_calendar: wrong hours scheduling')
td = timedelta()
for item in res:
td += item[1] - item[0]
@@ -362,38 +301,34 @@ class TestResource(TestResourceCommon):
# old API: resource without leaves
# res: 2 weeks -> 40 hours
res = self.resource_calendar._interval_hours_get(
cr, uid, self.calendar_id,
res = self.calendar._interval_hours_get(
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
resource_id=self.resource1_id, exclude_leaves=True, context=context)
resource_id=self.resource1_id, exclude_leaves=True)
self.assertEqual(res, 40.0, 'resource_calendar: wrong _interval_hours_get compatibility computation')
# new API: resource without leaves
# res: 2 weeks -> 40 hours
res = self.resource_calendar.get_working_hours(
cr, uid, self.calendar_id,
res = self.calendar.get_working_hours(
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
compute_leaves=False, resource_id=self.resource1_id, context=context)
compute_leaves=False, resource_id=self.resource1_id)
self.assertEqual(res, 40.0, 'resource_calendar: wrong get_working_hours computation')
# old API: resource and leaves
# res: 2 weeks -> 40 hours - (3+4) leave hours
res = self.resource_calendar._interval_hours_get(
cr, uid, self.calendar_id,
res = self.calendar._interval_hours_get(
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
resource_id=self.resource1_id, exclude_leaves=False, context=context)
resource_id=self.resource1_id, exclude_leaves=False)
self.assertEqual(res, 33.0, 'resource_calendar: wrong _interval_hours_get compatibility computation')
# new API: resource and leaves
# res: 2 weeks -> 40 hours - (3+4) leave hours
res = self.resource_calendar.get_working_hours(
cr, uid, self.calendar_id,
res = self.calendar.get_working_hours(
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0) + relativedelta(days=7),
compute_leaves=True, resource_id=self.resource1_id, context=context)
compute_leaves=True, resource_id=self.resource1_id)
self.assertEqual(res, 33.0, 'resource_calendar: wrong get_working_hours computation')
# --------------------------------------------------
@@ -401,69 +336,105 @@ class TestResource(TestResourceCommon):
# --------------------------------------------------
# Test without calendar and default_interval
res = self.resource_calendar.get_working_hours(
cr, uid, None,
res = self.ResourceCalendar.with_context(self.context).get_working_hours(
self.date1.replace(hour=6, minute=0),
self.date2.replace(hour=23, minute=0),
compute_leaves=True, resource_id=self.resource1_id,
default_interval=(8, 16), context=context)
default_interval=(8, 16))
self.assertEqual(res, 32.0, 'resource_calendar: wrong get_working_hours computation')
self.att0_0_id = self.resource_attendance.create(
cr, uid, {
self.att0_0_id = self.ResourceAttendance.with_context(self.context).create(
{
'name': 'Att0',
'dayofweek': '0',
'hour_from': 7.5,
'hour_to': 12.5,
'calendar_id': self.calendar_id,
}, context=context
'calendar_id': self.calendar.id,
}
)
self.att0_1_id = self.resource_attendance.create(
cr, uid, {
self.att0_1_id = self.ResourceAttendance.with_context(self.context).create(
{
'name': 'Att0',
'dayofweek': '0',
'hour_from': 13,
'hour_to': 14,
'calendar_id': self.calendar_id,
}, context=context
'calendar_id': self.calendar.id,
}
)
date1 = datetime.strptime('2013-02-11 07:30:00', '%Y-%m-%d %H:%M:%S')
date2 = datetime.strptime('2013-02-11 14:00:00', '%Y-%m-%d %H:%M:%S')
res = self.resource_calendar.get_working_hours(
cr, uid, self.calendar_id,
date1 = Datetime.from_string('2013-02-11 07:30:00')
date2 = Datetime.from_string('2013-02-11 14:00:00')
res = self.calendar.get_working_hours(
date1,
date2,
compute_leaves=False, resource_id=self.resource1_id, context=context)
compute_leaves=False, resource_id=self.resource1_id)
# 7h30 -> 12h30 = 5 / 13h -> 14h = 1 / -> 6h
self.assertEqual(res, 6, 'resource_calendar: wrong get_working_hours computation')
def test_50_calendar_schedule_days(self):
""" Testing calendar days scheduling """
cr, uid = self.cr, self.uid
_format = '%Y-%m-%d %H:%M:%S'
# --------------------------------------------------
# Test1: with calendar
# --------------------------------------------------
res = self.resource_calendar.schedule_days_get_date(cr, uid, self.calendar_id, 5, day_date=self.date1, context={'tz': 'UTC'})
self.assertEqual(res.date(), datetime.strptime('2013-02-26 00:0:00', _format).date(), 'resource_calendar: wrong days scheduling')
res = self.resource_calendar.schedule_days_get_date(cr, uid, self.calendar_id, -2, day_date=self.date1, context={'tz': 'UTC'})
self.assertEqual(res.date(), datetime.strptime('2013-02-08 00:00:00', _format).date(), 'resource_calendar: wrong days scheduling')
res = self.calendar.schedule_days_get_date(5, day_date=self.date1)
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=self.date1)
self.assertEqual(res.date(), Datetime.from_string('2013-02-08 00:00:00').date(), 'resource_calendar: wrong days scheduling')
res = self.resource_calendar.schedule_days_get_date(
cr, uid, self.calendar_id, 5, day_date=self.date1,
compute_leaves=True, resource_id=self.resource1_id, context={'tz': 'UTC'})
self.assertEqual(res.date(), datetime.strptime('2013-03-01 00:0:00', _format).date(), 'resource_calendar: wrong days scheduling')
res = self.calendar.schedule_days_get_date(
5, day_date=self.date1,
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')
# --------------------------------------------------
# Test2: misc
# --------------------------------------------------
# Without calendar, should only count days -> 12 -> 16, 5 days with default intervals
res = self.resource_calendar.schedule_days_get_date(cr, uid, None, 5, day_date=self.date1, default_interval=(8, 16), context={'tz': 'UTC'})
self.assertEqual(res, datetime.strptime('2013-02-16 16:00:00', _format), 'resource_calendar: wrong days scheduling')
res = self.ResourceCalendar.with_context(self.context).schedule_days_get_date(5, day_date=self.date1, default_interval=(8, 16))
self.assertEqual(res, Datetime.from_string('2013-02-16 16:00:00'), 'resource_calendar: wrong days scheduling')
def test_60_project(self):
# I assign working calendar '45 Hours/Week' to human resource.
resources = self.env.ref('resource.resource_analyst') + self.env.ref('resource.resource_designer') + self.env.ref('resource.resource_developer')
resources.write({'calendar_id': self.ref('resource.timesheet_group1'), 'resource_type': 'user'})
# I had Project of Odoo Integration of 50 Hours with three human resource assigned on it. I have started project from this week start.
# I check per day work hour availability of the Resource based on Working Calendar Assigned to each resource, for first day of the week.
now = datetime.now()
dt = now - timedelta(days=now.weekday())
for resource in resources:
result = resource.calendar_id.working_hours_on_day(dt)
self.assertEqual(float_compare(result, 8.0, precision_digits=2), 0, 'Wrong calculation of day work hour availability of the Resource (found %d).' % result)
# Now, resource "Developer" drafted leave on Thursday in this week.
now = datetime.now()
dt = (now - timedelta(days=now.weekday())) + timedelta(days=3)
vals = {
'resource_id': self.ref('resource.resource_developer'),
'calendar_id': self.ref('resource.timesheet_group1'),
'date_from': dt.strftime("%Y-%m-%d 09:00:00"),
'date_to': dt.strftime("%Y-%m-%d 18:00:00")
}
self.env.ref('resource.resource_dummyleave').write(vals)
# I check Actual working hours on resource 'Developer' from this week
now = datetime.now()
dt_from = now - relativedelta(days=now.weekday(), hour=8, minute=30)
dt_to = dt_from + relativedelta(days=6, hour=17)
hours = self.env.ref('resource.timesheet_group1').interval_hours_get(dt_from, dt_to, resource=self.ref('resource.resource_developer'))
self.assertGreater(hours, 27, 'Invalid Total Week working hour calculated, got %r, expected > 27' % hours)
# Project Analysis work is of 20 hours which will start from Week start so i will calculate working schedule for resource Analyst for the same.
now = datetime.now()
work_intreval = self.env.ref('resource.timesheet_group1').interval_min_get(now, 20.0, resource=self.ref('resource.resource_designer'))
self.assertGreaterEqual(len(work_intreval), 5, 'Wrong Schedule Calculated')
def test_70_duplicate_resource(self):
resource_id = self.env.ref('resource.resource_analyst').copy()
self.assertTrue(resource_id, 'Unable to Duplicate Resource')
WAR_START = date(1932, 11, 2)
WAR_END = date(1932, 12, 10)
@@ -569,10 +540,8 @@ class TestWorkDays(TransactionCase):
weekdays = [d for d in self._days if d.weekday() not in (5, 6)]
self.assertEqual(weekdays, list(r1._iter_work_days(WAR_START, WAR_END)))
self.assertEqual(
[d for d in weekdays
if d < date(1932, 11, 9) or d > date(1932, 11, 12)
],
self.assertEqual([
d for d in weekdays if d < date(1932, 11, 9) or d > date(1932, 11, 12)],
list(r2._iter_work_days(WAR_START, WAR_END))
)
@@ -593,12 +562,11 @@ class TestWorkDays(TransactionCase):
'resource_id': r.id
})
self.assertEqual(
[d for d in self._days
if d.weekday() not in (5, 6)
if d < date(1932, 11, 9) or d > date(1932, 11, 12)
if d < date(1932, 12, 2)
],
self.assertEqual([
d for d in self._days
if d.weekday() not in (5, 6)
if d < date(1932, 11, 9) or d > date(1932, 11, 12)
if d < date(1932, 12, 2)],
list(r._iter_work_days(WAR_START, WAR_END))
)
@@ -608,11 +576,11 @@ class TestWorkDays(TransactionCase):
self.assertTrue(r._is_work_day(date(1932, 11, 14)))
self.assertTrue(r._is_work_day(date(1932, 12, 1)))
self.assertFalse(r._is_work_day(date(1932, 11, 11))) # global leave
self.assertFalse(r._is_work_day(date(1932, 11, 13))) # sun
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
self.assertFalse(r._is_work_day(date(1932, 11, 11))) # global leave
self.assertFalse(r._is_work_day(date(1932, 11, 13))) # sun
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)
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<odoo>
<!-- Search Views -->
@@ -212,7 +211,7 @@
<form string="Leave Detail">
<group>
<group>
<field name="resource_id" on_change="onchange_resource(resource_id)"/>
<field name="resource_id"/>
<field name="name" string="Reason"/>
</group>
<group>
@@ -259,5 +258,4 @@
<menuitem action="resource.action_resource_calendar_form" id="menu_resource_calendar" parent="menu_resource_config" sequence="1"/>
<menuitem action="resource.action_resource_calendar_leave_tree" id="menu_view_resource_calendar_leaves_search" parent="menu_resource_config" sequence="2"/>
<menuitem action="resource.action_resource_resource_tree" id="menu_resource_resource" parent="menu_resource_config" sequence="3"/>
</data>
</openerp>
</odoo>
+11 -12
View File
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from odoo import api, fields, models
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
class ResourceCalendarAttendance(models.Model):
@@ -16,16 +14,16 @@ class ResourceCalendarAttendance(models.Model):
class ResourceCalendarLeaves(models.Model):
_inherit = "resource.calendar.leaves"
group_id = fields.Many2one('procurement.group', 'Procurement Group')
group_id = fields.Many2one('procurement.group', string="Procurement Group")
class ResourceCalendar(models.Model):
_inherit = "resource.calendar"
# Keep as it takes into account times
def get_leave_intervals(self, cr, uid, id, resource_id=None,
start_datetime=None, end_datetime=None,
context=None):
@api.multi
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.
@@ -43,15 +41,15 @@ class ResourceCalendar(models.Model):
"""
# TDE FIXME: waw, overriding completely a method + changing its result
# and its behavior, very nice. Please FIXME.
resource_calendar = self.browse(cr, uid, id, context=context)
self.ensure_one()
leaves = []
for leave in resource_calendar.leave_ids:
for leave in self.leave_ids:
if leave.resource_id and not resource_id == leave.resource_id.id:
continue
date_from = datetime.datetime.strptime(leave.date_from, DEFAULT_SERVER_DATETIME_FORMAT)
date_from = fields.Datetime.from_string(leave.date_from)
if end_datetime and date_from > end_datetime:
continue
date_to = datetime.datetime.strptime(leave.date_to, DEFAULT_SERVER_DATETIME_FORMAT)
date_to = fields.Datetime.from_string(leave.date_to)
if start_datetime and date_to < start_datetime:
continue
leaves.append((date_from, date_to, leave.group_id.id))
@@ -61,7 +59,8 @@ class ResourceCalendar(models.Model):
# Utility methods
# --------------------------------------------------
def interval_remove_leaves(self, cr, uid, interval, leave_intervals, context=None):
@api.model
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
@@ -101,7 +100,7 @@ class ResourceCalendar(models.Model):
att_obj = self.pool.get("resource.calendar.attendance")
if leave[2]:
if len(current_interval) > 2:
current_group = current_interval[2] and att_obj.browse(cr, uid, current_interval[2], context=context).group_id.id or False
current_group = current_interval[2] and att_obj.browse(current_interval[2]).group_id.id or False
if leave[2] != current_group:
continue
if leave[1] <= current_interval[0]:
+5 -5
View File
@@ -68,7 +68,7 @@ class StockWarehouseOrderpoint(models.Model):
purchase_date = False
delivery_date = start_date
if self.calendar_id and self.calendar_id.attendance_ids:
res = self.calendar_id._schedule_days(-1, start_date, compute_leaves=True)[0] # CLEANME
res = self.calendar_id._schedule_days(-1, start_date, compute_leaves=True)
if res and res[0][0] < start_date:
group_to_find = res[0][2] and Attendance.browse(res[0][2]).group_id.id
delivery_date = res[0][0]
@@ -76,7 +76,7 @@ class StockWarehouseOrderpoint(models.Model):
if self.purchase_calendar_id and self.purchase_calendar_id.attendance_ids:
while not purchase_date:
found_date = found_date + relativedelta(days=-1) # won't allow to deliver within the day
res = self.purchase_calendar_id._schedule_days(-1, found_date, compute_leaves=True)[0] # CLEANME
res = self.purchase_calendar_id._schedule_days(-1, found_date, compute_leaves=True)
for re in res:
group = re[2] and Attendance.browse(re[2]).group_id.id
found_date = re[0]
@@ -94,7 +94,7 @@ class StockWarehouseOrderpoint(models.Model):
now_date = datetime.utcnow()
# Search first calendar day (without group)
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)[0] # CLEANME
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)
att_group = res and res[0][2] and Attendance.browse(res[0][2]).group_id.id
# If hours are smaller than the current date, search a day further
if res and res[0][0] < now_date:
@@ -112,7 +112,7 @@ class StockWarehouseOrderpoint(models.Model):
while res and group and att_group != group and number < 100:
number += 1
new_date = res[0][1] + relativedelta(days=1)
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)[0]
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)
att_group = False
for re in res:
if re[2]:
@@ -128,7 +128,7 @@ class StockWarehouseOrderpoint(models.Model):
if res:
date1 = res[0][1]
new_date = res[0][1] + relativedelta(days=1)
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)[0]
res = self.calendar_id._schedule_days(1, new_date, compute_leaves=True)
if res:
return (date1, res[0][1])
return (False, False)