85 lines
3.7 KiB
Python
85 lines
3.7 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
|
|
from odoo import api, models, _
|
|
from odoo.exceptions import ValidationError
|
|
from odoo.osv.expression import AND
|
|
from odoo.tools import format_date
|
|
|
|
|
|
class HrLeave(models.Model):
|
|
_inherit = 'hr.leave'
|
|
|
|
def _compute_resource_calendar_id(self):
|
|
super()._compute_resource_calendar_id()
|
|
for leave in self.filtered(lambda l: l.employee_id):
|
|
# We use the request dates to find the contracts, because date_from
|
|
# and date_to are not set yet at this point. Since these dates are
|
|
# used to get the contracts for which these leaves apply and
|
|
# contract start- and end-dates are just dates (and not datetimes)
|
|
# these dates are comparable.
|
|
if leave.employee_id:
|
|
contracts = self.env['hr.contract'].search([
|
|
'|', ('state', 'in', ['open', 'close']),
|
|
'&', ('state', '=', 'draft'),
|
|
('kanban_state', '=', 'done'),
|
|
('employee_id', '=', leave.employee_id.id),
|
|
('date_start', '<=', leave.request_date_to),
|
|
'|', ('date_end', '=', False),
|
|
('date_end', '>=', leave.request_date_from),
|
|
])
|
|
if contracts:
|
|
# If there are more than one contract they should all have the
|
|
# same calendar, otherwise a constraint is violated.
|
|
leave.resource_calendar_id = contracts[:1].resource_calendar_id
|
|
|
|
def _get_overlapping_contracts(self, contract_states=None):
|
|
self.ensure_one()
|
|
if contract_states is None:
|
|
contract_states = [
|
|
'|',
|
|
('state', 'not in', ['draft', 'cancel']),
|
|
'&',
|
|
('state', '=', 'draft'),
|
|
('kanban_state', '=', 'done')
|
|
]
|
|
domain = AND([contract_states, [
|
|
('employee_id', '=', self.employee_id.id),
|
|
('date_start', '<=', self.date_to),
|
|
'|',
|
|
('date_end', '>=', self.date_from),
|
|
('date_end', '=', False),
|
|
]])
|
|
return self.env['hr.contract'].sudo().search(domain)
|
|
|
|
@api.constrains('date_from', 'date_to')
|
|
def _check_contracts(self):
|
|
"""
|
|
A leave cannot be set across multiple contracts.
|
|
Note: a leave can be across multiple contracts despite this constraint.
|
|
It happens if a leave is correctly created (not across multiple contracts) but
|
|
contracts are later modifed/created in the middle of the leave.
|
|
"""
|
|
for holiday in self.filtered('employee_id'):
|
|
contracts = holiday._get_overlapping_contracts()
|
|
if len(contracts.resource_calendar_id) > 1:
|
|
state_labels = {e[0]: e[1] for e in contracts._fields['state']._description_selection(self.env)}
|
|
raise ValidationError(
|
|
_("""A leave cannot be set across multiple contracts with different working schedules.
|
|
|
|
Please create one time off for each contract.
|
|
|
|
Time off:
|
|
%(time_off)s
|
|
|
|
Contracts:
|
|
%(contracts)s""",
|
|
time_off=holiday.display_name,
|
|
contracts='\n'.join(_(
|
|
"Contract %(contract)s from %(start_date)s to %(end_date)s, status: %(status)s",
|
|
contract=contract.name,
|
|
start_date=format_date(self.env, contract.date_start),
|
|
end_date=format_date(self.env, contract.date_end) if contract.date_end else _("undefined"),
|
|
status=state_labels[contract.state]
|
|
) for contract in contracts)))
|