Purpose ======= In order to be able to manage payroll, we need to know if a resource calendar is a full time or a part time. For instance, in belgium, 23h a week is a full time for a teacher but in cp 200 it is 38h. In belgium every employee can take a parental leave in part time but he cannot take it in part time if they are not full time. Having a field indicating if the contract is full time or not is useful for computing salary rules. Specification ============= On the calendar model - Display a computed field with the number of hours in the calendar - Display a field with the required number of hours to be full time - Display a computed checkbox, ticked if full time or not On the contract model - Add a related on these fields, to ease the access on the salary rules computation. closes odoo/odoo#30034
78 lines
3.5 KiB
Python
78 lines
3.5 KiB
Python
# -*- 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, OR
|
|
from odoo.tools import float_compare
|
|
|
|
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)
|
|
|
|
|
|
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_type, 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
|
|
benefit_type_ids = benefit_type.ids
|
|
if benefit_type == self.env.ref('hr_payroll.benefit_type_attendance'): # special case for global attendances
|
|
benefit_type_ids += [False]# no benefit type = normal/global attendance
|
|
domain = [('benefit_type_id', 'in', benefit_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)
|
|
# actual hours per day
|
|
if benefit_type.is_leave:
|
|
intervals = calendar._attendance_intervals(from_datetime, to_datetime, resource) & calendar._leave_intervals(from_datetime, to_datetime, resource, domain) # use domain to only retrieve leaves of this type
|
|
else:
|
|
intervals = calendar._attendance_intervals(from_datetime, to_datetime, resource, domain) - calendar._leave_intervals(from_datetime, to_datetime, resource)
|
|
|
|
return self._get_days_data(intervals, day_total)
|