mirror of
https://github.com/bringout/oca-ocb-hr.git
synced 2026-04-26 19:52:02 +02:00
176 lines
7.6 KiB
Python
176 lines
7.6 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
from calendar import monthrange
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
from odoo.addons.hr_holidays.models.hr_leave_accrual_plan_level import _get_selection_days
|
|
|
|
|
|
class HrLeaveAccrualPlan(models.Model):
|
|
_name = 'hr.leave.accrual.plan'
|
|
_description = "Accrual Plan"
|
|
|
|
active = fields.Boolean(default=True)
|
|
name = fields.Char('Name', required=True)
|
|
time_off_type_id = fields.Many2one('hr.leave.type', string="Time Off Type",
|
|
check_company=True, index='btree_not_null',
|
|
help="""Specify if this accrual plan can only be used with this Time Off Type.
|
|
Leave empty if this accrual plan can be used with any Time Off Type.""")
|
|
employees_count = fields.Integer("Employees", compute='_compute_employee_count')
|
|
level_ids = fields.One2many('hr.leave.accrual.level', 'accrual_plan_id', copy=True, string="Milestones")
|
|
allocation_ids = fields.One2many('hr.leave.allocation', 'accrual_plan_id',
|
|
export_string_translation=False)
|
|
company_id = fields.Many2one('res.company', string='Company', domain=lambda self: [('id', 'in', self.env.companies.ids)],
|
|
compute="_compute_company_id", store="True", readonly=False)
|
|
transition_mode = fields.Selection([
|
|
('immediately', 'Immediately'),
|
|
('end_of_accrual', "After this accrual's period")],
|
|
export_string_translation=False, default="immediately", required=True)
|
|
show_transition_mode = fields.Boolean(compute='_compute_show_transition_mode', export_string_translation=False)
|
|
is_based_on_worked_time = fields.Boolean(compute="_compute_is_based_on_worked_time", store=True, readonly=False,
|
|
export_string_translation=False,
|
|
help="Only excludes requests where the time off type is set as unpaid kind of.")
|
|
accrued_gain_time = fields.Selection([
|
|
("start", "At the start of the accrual period"),
|
|
("end", "At the end of the accrual period")],
|
|
export_string_translation=False,
|
|
default="end", required=True)
|
|
can_be_carryover = fields.Boolean(export_string_translation=False)
|
|
carryover_date = fields.Selection([
|
|
("year_start", "At the start of the year"),
|
|
("allocation", "At the allocation date"),
|
|
("other", "Custom date")],
|
|
export_string_translation=False,
|
|
default="year_start", required=True, string="Carry-Over Time")
|
|
carryover_day = fields.Selection(
|
|
_get_selection_days, compute='_compute_carryover_day',
|
|
export_string_translation=False, store=True, readonly=False, default='1')
|
|
carryover_month = fields.Selection([
|
|
("1", "January"),
|
|
("2", "February"),
|
|
("3", "March"),
|
|
("4", "April"),
|
|
("5", "May"),
|
|
("6", "June"),
|
|
("7", "July"),
|
|
("8", "August"),
|
|
("9", "September"),
|
|
("10", "October"),
|
|
("11", "November"),
|
|
("12", "December")
|
|
], export_string_translation=False, default=lambda self: str((fields.Date.today()).month))
|
|
added_value_type = fields.Selection([('day', 'Days'), ('hour', 'Hours')],
|
|
export_string_translation=False, default="day", store=True)
|
|
|
|
@api.depends('level_ids')
|
|
def _compute_show_transition_mode(self):
|
|
for plan in self:
|
|
plan.show_transition_mode = len(plan.level_ids) > 1
|
|
|
|
level_count = fields.Integer('Levels', compute='_compute_level_count')
|
|
|
|
@api.depends('level_ids')
|
|
def _compute_level_count(self):
|
|
level_read_group = self.env['hr.leave.accrual.level']._read_group(
|
|
[('accrual_plan_id', 'in', self.ids)],
|
|
groupby=['accrual_plan_id'],
|
|
aggregates=['__count'],
|
|
)
|
|
mapped_count = {accrual_plan.id: count for accrual_plan, count in level_read_group}
|
|
for plan in self:
|
|
plan.level_count = mapped_count.get(plan.id, 0)
|
|
|
|
@api.depends('allocation_ids')
|
|
def _compute_employee_count(self):
|
|
allocations_read_group = self.env['hr.leave.allocation']._read_group(
|
|
[('accrual_plan_id', 'in', self.ids)],
|
|
['accrual_plan_id'],
|
|
['employee_id:count_distinct'],
|
|
)
|
|
allocations_dict = {accrual_plan.id: count for accrual_plan, count in allocations_read_group}
|
|
for plan in self:
|
|
plan.employees_count = allocations_dict.get(plan.id, 0)
|
|
|
|
@api.depends('time_off_type_id.company_id')
|
|
def _compute_company_id(self):
|
|
for accrual_plan in self:
|
|
if accrual_plan.time_off_type_id:
|
|
accrual_plan.company_id = accrual_plan.time_off_type_id.company_id
|
|
else:
|
|
accrual_plan.company_id = self.env.company
|
|
|
|
@api.depends("accrued_gain_time")
|
|
def _compute_is_based_on_worked_time(self):
|
|
for plan in self:
|
|
if plan.accrued_gain_time == "start":
|
|
plan.is_based_on_worked_time = False
|
|
|
|
@api.depends("carryover_month")
|
|
def _compute_carryover_day(self):
|
|
for plan in self:
|
|
# 2020 is a leap year, so monthrange(2020, february) will return [2, 29]
|
|
plan.carryover_day = str(min(monthrange(2020, int(plan.carryover_month))[1], int(plan.carryover_day)))
|
|
|
|
def action_open_accrual_plan_employees(self):
|
|
self.ensure_one()
|
|
return {
|
|
'name': _("Accrual Plan's Employees"),
|
|
'type': 'ir.actions.act_window',
|
|
'view_mode': 'kanban,list,form',
|
|
'res_model': 'hr.employee',
|
|
'domain': [('id', 'in', self.allocation_ids.employee_id.ids)],
|
|
}
|
|
|
|
def action_create_accrual_plan_level(self):
|
|
return {
|
|
'name': self.env._('New Milestone'),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'hr.leave.accrual.level',
|
|
'view_mode': 'form',
|
|
'views': [[False, 'form']],
|
|
'view_id': self.env.ref('hr_holidays.hr_accrual_level_view_form').id,
|
|
'target': 'new',
|
|
'context': dict(
|
|
self.env.context,
|
|
new=True,
|
|
default_can_be_carryover=self.can_be_carryover,
|
|
default_accrued_gain_time=self.accrued_gain_time,
|
|
default_can_modify_value_type=not self.time_off_type_id and not self.level_ids,
|
|
default_added_value_type=self.added_value_type,
|
|
),
|
|
}
|
|
|
|
def action_open_accrual_plan_level(self, level_id):
|
|
return {
|
|
'name': self.env._('Milestone Edition'),
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'hr.leave.accrual.level',
|
|
'view_mode': 'form',
|
|
'views': [[False, 'form']],
|
|
'target': 'new',
|
|
'res_id': level_id,
|
|
}
|
|
|
|
def copy_data(self, default=None):
|
|
vals_list = super().copy_data(default=default)
|
|
return [dict(vals, name=self.env._("%s (copy)", plan.name)) for plan, vals in zip(self, vals_list)]
|
|
|
|
@api.ondelete(at_uninstall=False)
|
|
def _prevent_used_plan_unlink(self):
|
|
domain = [
|
|
('allocation_type', '=', 'accrual'),
|
|
('accrual_plan_id', 'in', self.ids),
|
|
('state', 'not in', ('cancel', 'refuse')),
|
|
]
|
|
if self.env['hr.leave.allocation'].search_count(domain):
|
|
raise ValidationError(_(
|
|
"Some of the accrual plans you're trying to delete are linked to an existing allocation. Delete or cancel them first."
|
|
))
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if not vals.get("name", False):
|
|
vals['name'] = self.env._("Unnamed Plan")
|
|
return super().create(vals_list)
|