2018-01-16 06:58:15 +01:00
|
|
|
# -*- coding: utf-8 -*-
|
2018-01-16 11:34:37 +01:00
|
|
|
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
from datetime import timedelta
|
|
|
|
|
2018-01-16 11:34:37 +01:00
|
|
|
from flectra import api, fields, models
|
|
|
|
from flectra.tools import float_utils
|
2018-01-16 06:58:15 +01:00
|
|
|
|
|
|
|
class ResourceMixin(models.AbstractModel):
|
|
|
|
_name = "resource.mixin"
|
|
|
|
_description = 'Resource Mixin'
|
|
|
|
|
|
|
|
resource_id = fields.Many2one(
|
|
|
|
'resource.resource', 'Resource',
|
|
|
|
auto_join=True, index=True, ondelete='restrict', required=True)
|
|
|
|
company_id = fields.Many2one(
|
|
|
|
'res.company', 'Company',
|
|
|
|
default=lambda self: self.env['res.company']._company_default_get(),
|
|
|
|
index=True, related='resource_id.company_id', store=True)
|
|
|
|
resource_calendar_id = fields.Many2one(
|
|
|
|
'resource.calendar', 'Working Hours',
|
|
|
|
default=lambda self: self.env['res.company']._company_default_get().resource_calendar_id,
|
|
|
|
index=True, related='resource_id.calendar_id')
|
|
|
|
|
|
|
|
@api.model
|
|
|
|
def create(self, values):
|
|
|
|
if not values.get('resource_id'):
|
|
|
|
resource = self.env['resource.resource'].create({
|
|
|
|
'name': values.get(self._rec_name)
|
|
|
|
})
|
|
|
|
values['resource_id'] = resource.id
|
|
|
|
return super(ResourceMixin, self).create(values)
|
|
|
|
|
|
|
|
@api.multi
|
|
|
|
def copy_data(self, default=None):
|
|
|
|
if default is None:
|
|
|
|
default = {}
|
|
|
|
resource = self.resource_id.copy()
|
|
|
|
default['resource_id'] = resource.id
|
|
|
|
default['company_id'] = resource.company_id.id
|
|
|
|
default['resource_calendar_id'] = resource.calendar_id.id
|
|
|
|
return super(ResourceMixin, self).copy_data(default)
|
|
|
|
|
|
|
|
def get_work_days_count(self, from_datetime, to_datetime, calendar=None):
|
|
|
|
""" Return the number of work days for the resource, taking into account
|
|
|
|
leaves. An optional calendar can be given in case multiple calendars can
|
|
|
|
be used on the resource. """
|
|
|
|
return self.get_work_days_data(from_datetime, to_datetime, calendar=calendar)['days']
|
|
|
|
|
|
|
|
def get_work_days_data(self, from_datetime, to_datetime, calendar=None):
|
|
|
|
days_count = 0.0
|
|
|
|
total_work_time = timedelta()
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
for day_intervals in calendar._iter_work_intervals(
|
|
|
|
from_datetime, to_datetime, self.resource_id.id,
|
|
|
|
compute_leaves=True):
|
|
|
|
theoric_hours = self.get_day_work_hours_count(day_intervals[0][0].date(), calendar=calendar)
|
|
|
|
work_time = sum((interval[1] - interval[0] for interval in day_intervals), timedelta())
|
|
|
|
total_work_time += work_time
|
2018-04-05 10:25:40 +02:00
|
|
|
if theoric_hours:
|
|
|
|
days_count += float_utils.round((work_time.total_seconds() / 3600 / theoric_hours) * 4) / 4
|
2018-01-16 06:58:15 +01:00
|
|
|
return {
|
|
|
|
'days': days_count,
|
|
|
|
'hours': total_work_time.total_seconds() / 3600,
|
|
|
|
}
|
|
|
|
|
|
|
|
def iter_works(self, from_datetime, to_datetime, calendar=None):
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
return calendar._iter_work_intervals(from_datetime, to_datetime, self.resource_id.id)
|
|
|
|
|
|
|
|
def iter_work_hours_count(self, from_datetime, to_datetime, calendar=None):
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
return calendar._iter_work_hours_count(from_datetime, to_datetime, self.resource_id.id)
|
|
|
|
|
|
|
|
def get_leaves_day_count(self, from_datetime, to_datetime, calendar=None):
|
|
|
|
""" Return the number of leave days for the resource, taking into account
|
|
|
|
attendances. An optional calendar can be given in case multiple calendars
|
|
|
|
can be used on the resource. """
|
|
|
|
days_count = 0.0
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
for day_intervals in calendar._iter_leave_intervals(from_datetime, to_datetime, self.resource_id.id):
|
|
|
|
theoric_hours = self.get_day_work_hours_count(day_intervals[0][0].date(), calendar=calendar)
|
|
|
|
leave_time = sum((interval[1] - interval[0] for interval in day_intervals), timedelta())
|
2018-04-05 10:25:40 +02:00
|
|
|
if theoric_hours:
|
|
|
|
days_count += float_utils.round((leave_time.total_seconds() / 3600 / theoric_hours) * 4) / 4
|
2018-01-16 06:58:15 +01:00
|
|
|
return days_count
|
|
|
|
|
|
|
|
def iter_leaves(self, from_datetime, to_datetime, calendar=None):
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
return calendar._iter_leave_intervals(from_datetime, to_datetime, self.resource_id.id)
|
|
|
|
|
|
|
|
def get_start_work_hour(self, day_dt, calendar=None):
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
work_intervals = calendar._get_day_work_intervals(day_dt, resource_id=self.resource_id.id)
|
|
|
|
return work_intervals and work_intervals[0][0]
|
|
|
|
|
|
|
|
def get_end_work_hour(self, day_dt, calendar=None):
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
work_intervals = calendar._get_day_work_intervals(day_dt, resource_id=self.resource_id.id)
|
|
|
|
return work_intervals and work_intervals[-1][1]
|
|
|
|
|
|
|
|
def get_day_work_hours_count(self, day_date, calendar=None):
|
|
|
|
calendar = calendar or self.resource_calendar_id
|
|
|
|
attendances = calendar._get_day_attendances(day_date, False, False)
|
|
|
|
if not attendances:
|
|
|
|
return 0
|
|
|
|
return sum(float(i.hour_to) - float(i.hour_from) for i in attendances)
|