/
resource.py
110 lines (82 loc) · 4.94 KB
/
resource.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# -*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, fields, api
from odoo.osv.expression import AND
from odoo.tools import float_compare
from datetime import datetime
class ResourceCalendar(models.Model):
_inherit = 'resource.calendar'
hours_per_week = fields.Float(compute="_compute_hours_per_week", string="Hours per Week")
full_time_required_hours = fields.Float(string="Fulltime Hours", help="Number of hours to work to be considered as fulltime.")
is_fulltime = fields.Boolean(compute='_compute_is_fulltime', string="Is Full Time")
# UI fields
normal_attendance_ids = fields.One2many(
'resource.calendar.attendance', 'calendar_id', 'Normal working Time',
domain=[('resource_id', '=', False)])
extra_attendance_ids = fields.One2many(
'resource.calendar.attendance', 'calendar_id', 'Employees working Time',
domain=[('resource_id', '!=', False)])
@api.depends('normal_attendance_ids.hour_from', 'normal_attendance_ids.hour_to')
def _compute_hours_per_week(self):
for calendar in self:
calendar.hours_per_week = sum((attendance.hour_to - attendance.hour_from) for attendance in calendar.normal_attendance_ids)
def _compute_is_fulltime(self):
for calendar in self:
calendar.is_fulltime = not float_compare(calendar.full_time_required_hours, calendar.hours_per_week, 3)
def _get_global_attendances(self):
res = super(ResourceCalendar, self)._get_global_attendances()
res |= self.normal_attendance_ids.filtered(lambda attendance: not attendance.date_from and not attendance.date_to)
return res
# Add a key on the api.onchange decorator
@api.onchange('attendance_ids', 'normal_attendance_ids')
def _onchange_hours_per_day(self):
return super(ResourceCalendar, self)._onchange_hours_per_day()
@api.multi
def transfer_leaves_to(self, other_calendar, resources=None, from_date=None):
"""
Transfer some resource.calendar.leaves from 'self' to another calendar 'other_calendar'.
Transfered leaves linked to `resources` (or all if `resources` is None) and starting
after 'from_date' (or today if None).
"""
from_date = from_date or datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
domain = [
('calendar_id', 'in', self.ids),
('date_from', '>=', from_date),
]
domain = AND([domain, [('resource_id', 'in', resources.ids)]]) if resources else domain
self.env['resource.calendar.leaves'].search(domain).write({
'calendar_id': other_calendar.id,
})
class ResourceCalendarAttendance(models.Model):
_inherit = 'resource.calendar.attendance'
def _default_benefit_type_id(self):
return self.env.ref('hr_payroll.benefit_type_attendance', raise_if_not_found=False)
benefit_type_id = fields.Many2one('hr.benefit.type', 'Benefit Type', default=_default_benefit_type_id)
class ResourceCalendarLeave(models.Model):
_inherit = 'resource.calendar.leaves'
benefit_type_id = fields.Many2one('hr.benefit.type', 'Benefit Type')
class ResourceMixin(models.AbstractModel):
_inherit = "resource.mixin"
def get_benefit_days_data(self, benefit_types, from_datetime, to_datetime, calendar=None):
"""
By default the resource calendar is used, but it can be
changed using the `calendar` argument.
Returns a dict {'days': n, 'hours': h} containing the number of leaves
expressed as days and as hours.
"""
resource = self.resource_id
calendar = calendar or self.resource_calendar_id
type_leave = benefit_types.filtered(lambda t: t.is_leave)
type_attendance = benefit_types - type_leave
leave_domain = [('benefit_type_id', 'in', type_leave.ids)]
attendance_type_ids = type_attendance.ids
if self.env.ref('hr_payroll.benefit_type_attendance') in type_attendance: # special case for global attendances
attendance_type_ids += [False] # no benefit type = normal/global attendance
attendance_domain = [('benefit_type_id', 'in', attendance_type_ids)]
# naive datetimes are made explicit in UTC
from_datetime = self._timezone_datetime(from_datetime)
to_datetime = self._timezone_datetime(to_datetime)
day_total = self._get_day_total(from_datetime, to_datetime, calendar, resource)
leave_intervals = calendar._attendance_intervals(from_datetime, to_datetime, resource) & calendar._leave_intervals(from_datetime, to_datetime, resource, leave_domain) # use domain to only retrieve leaves of this type
attendance_intervals = calendar._attendance_intervals(from_datetime, to_datetime, resource, attendance_domain) - calendar._leave_intervals(from_datetime, to_datetime, resource)
return self._get_days_data(leave_intervals | attendance_intervals, day_total)