feature/odoo18 #2
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
# always loaded
|
||||
'data': [
|
||||
'security/security.xml',
|
||||
'views/hr_employee.xml',
|
||||
'views/hr_timeoff.xml'
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from asyncore import write
|
||||
from calendar import month
|
||||
|
||||
from dateutil.utils import today
|
||||
|
|
@ -7,6 +8,7 @@ from datetime import datetime, date, time, timedelta
|
|||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
from odoo.addons.hr_holidays.models.hr_leave import HolidaysRequest
|
||||
|
||||
class hrLeaveAccrualLevel(models.Model):
|
||||
_inherit = 'hr.leave.accrual.level'
|
||||
|
|
@ -260,6 +262,46 @@ class HRLeave(models.Model):
|
|||
"\nThe status is 'Approved', when time off request is approved by manager." +
|
||||
"\nThe status is 'Cancelled', when time off request is cancelled.")
|
||||
|
||||
submitted_date = fields.Datetime(string="Submit Date")
|
||||
|
||||
|
||||
|
||||
def write(self, values):
|
||||
is_officer = self.env.user.has_group('hr_holidays.group_hr_holidays_user') or self.env.is_superuser()
|
||||
if not is_officer and values.keys() - {'attachment_ids', 'supported_attachment_ids', 'message_main_attachment_id'}:
|
||||
# if any(hol.date_from.date() < fields.Date.today() and hol.employee_id.leave_manager_id != self.env.user for hol in self):
|
||||
# raise UserError(_('You must have manager rights to modify/validate a time off that already begun'))
|
||||
if any(leave.state == 'cancel' for leave in self):
|
||||
# raise UserError(_('Only a manager can modify a canceled leave.'))
|
||||
pass
|
||||
# Unlink existing resource.calendar.leaves for validated time off
|
||||
if 'state' in values and values['state'] != 'validate':
|
||||
validated_leaves = self.filtered(lambda l: l.state == 'validate')
|
||||
validated_leaves._remove_resource_leave()
|
||||
|
||||
employee_id = values.get('employee_id', False)
|
||||
if not self.env.context.get('leave_fast_create'):
|
||||
if values.get('state'):
|
||||
self._check_approval_update(values['state'])
|
||||
if any(holiday.validation_type == 'both' for holiday in self):
|
||||
if values.get('employee_id'):
|
||||
employees = self.env['hr.employee'].browse(values.get('employee_id'))
|
||||
else:
|
||||
employees = self.mapped('employee_id')
|
||||
self._check_double_validation_rules(employees, values['state'])
|
||||
if 'date_from' in values:
|
||||
values['request_date_from'] = values['date_from']
|
||||
if 'date_to' in values:
|
||||
values['request_date_to'] = values['date_to']
|
||||
result = super(HolidaysRequest, self).write(values)
|
||||
if any(field in values for field in ['request_date_from', 'date_from', 'request_date_from', 'date_to', 'holiday_status_id', 'employee_id', 'state']):
|
||||
self._check_validity()
|
||||
if not self.env.context.get('leave_fast_create'):
|
||||
for holiday in self:
|
||||
if employee_id:
|
||||
holiday.add_follower(employee_id)
|
||||
|
||||
return result
|
||||
|
||||
def _check_validity(self):
|
||||
for rec in self:
|
||||
|
|
@ -293,7 +335,7 @@ class HRLeave(models.Model):
|
|||
for rec in self:
|
||||
if rec.employee_id.user_id.id != self.env.user.id:
|
||||
raise ValidationError(_("Only employee can submit his own leave"))
|
||||
|
||||
rec.submitted_date = fields.Datetime.now()
|
||||
self._check_validity()
|
||||
rec.state = 'confirm'
|
||||
|
||||
|
|
@ -311,7 +353,29 @@ class HRLeave(models.Model):
|
|||
def action_approve(self):
|
||||
for rec in self:
|
||||
if rec.employee_id.leave_manager_id.id != self.env.user.id :
|
||||
raise ValidationError(_("Only Employees Time Off Approver can approve this "))
|
||||
raise ValidationError(_("Only Employees Time Off Manager can approve this Leave request"))
|
||||
return super(HRLeave, self).action_approve()
|
||||
|
||||
def action_refuse(self):
|
||||
for rec in self:
|
||||
if (rec.employee_id.leave_manager_id.id != self.env.user.id) and (self.env.user.id not in rec.holiday_status_id.responsible_ids.ids):
|
||||
raise ValidationError(_("only Employee / Leave type Time off Manager's can refuse this Leave request"))
|
||||
return super(HRLeave, self).action_refuse()
|
||||
|
||||
|
||||
def action_validate(self, check_state=True):
|
||||
current_employee = self.env.user.employee_id
|
||||
for holiday in self:
|
||||
if check_state and holiday.state in ['validate1'] and holiday.validation_type == 'both' and (holiday.holiday_status_id.responsible_ids and (current_employee.user_id.id not in holiday.holiday_status_id.responsible_ids.ids)):
|
||||
raise UserError(_('Only Timeoff officers for the %s can validate this leave'%(holiday.holiday_status_id.name)))
|
||||
|
||||
return super(HRLeave, self).action_validate(check_state)
|
||||
|
||||
@api.depends_context('uid')
|
||||
@api.depends('state', 'employee_id')
|
||||
def _compute_can_cancel(self):
|
||||
for leave in self:
|
||||
leave.can_cancel = leave.id and leave.employee_id.user_id == self.env.user and leave.state in ['confirm']
|
||||
|
||||
@api.ondelete(at_uninstall=False)
|
||||
def _unlink_if_correct_states(self):
|
||||
|
|
@ -323,13 +387,60 @@ class HRLeave(models.Model):
|
|||
for hol in self:
|
||||
if hol.state not in ['draft', 'cancel']:
|
||||
raise UserError(error_message % state_description_values.get(self[:1].state))
|
||||
if hol.date_from.date() < now:
|
||||
raise UserError(_('You cannot delete a time off which is in the past'))
|
||||
else:
|
||||
for holiday in self.filtered(lambda holiday: holiday.state not in ['cancel', 'draft']):
|
||||
raise UserError(error_message % (state_description_values.get(holiday.state),))
|
||||
|
||||
|
||||
def _check_approval_update(self, state):
|
||||
""" Check if target state is achievable. """
|
||||
if self.env.is_superuser():
|
||||
return
|
||||
|
||||
current_employee = self.env.user.employee_id
|
||||
is_officer = self.env.user.has_group('hr_holidays.group_hr_holidays_user')
|
||||
is_manager = self.env.user.has_group('hr_holidays.group_hr_holidays_manager')
|
||||
|
||||
for holiday in self:
|
||||
val_type = holiday.validation_type
|
||||
|
||||
if not is_manager:
|
||||
if holiday.state == 'cancel' and state != 'confirm':
|
||||
raise UserError(_('A cancelled leave cannot be modified.'))
|
||||
if state == 'confirm':
|
||||
if holiday.state == 'refuse':
|
||||
raise UserError(_('Only a Time Off Manager can reset a refused leave.'))
|
||||
# if holiday.date_from and holiday.date_from.date() <= fields.Date.today():
|
||||
# raise UserError(_('Only a Time Off Manager can reset a started leave.'))
|
||||
if holiday.employee_id != current_employee:
|
||||
raise UserError(_('Only a Time Off Manager can reset other people leaves.'))
|
||||
else:
|
||||
if val_type == 'no_validation' and current_employee == holiday.employee_id and (is_officer or is_manager):
|
||||
continue
|
||||
# use ir.rule based first access check: department, members, ... (see security.xml)
|
||||
holiday.check_access('write')
|
||||
|
||||
# This handles states validate1 validate and refuse
|
||||
if holiday.employee_id == current_employee\
|
||||
and self.env.user != holiday.employee_id.leave_manager_id\
|
||||
and not is_officer:
|
||||
raise UserError(_('Only a Time Off Officer or Manager can approve/refuse its own requests.'))
|
||||
|
||||
if (state == 'validate1' and val_type == 'both'):
|
||||
if not is_officer and self.env.user != holiday.employee_id.leave_manager_id:
|
||||
raise UserError(_('You must be either %s\'s manager or Time off Manager to approve this leave') % (holiday.employee_id.name))
|
||||
|
||||
if (state == 'validate' and val_type == 'manager')\
|
||||
and self.env.user != holiday.employee_id.leave_manager_id\
|
||||
and not is_officer:
|
||||
raise UserError(_("You must be %s's Manager to approve this leave", holiday.employee_id.name))
|
||||
|
||||
if not is_officer and (state == 'validate' and val_type == 'hr'):
|
||||
raise UserError(_('You must either be a Time off Officer or Time off Manager to approve this leave'))
|
||||
|
||||
HolidaysRequest.write = HRLeave.write
|
||||
|
||||
|
||||
class HRLeaveType(models.Model):
|
||||
_inherit='hr.leave.type'
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<function model="ir.model.data" name="write">
|
||||
<value model="ir.model.data" search="[('module', '=', 'hr_holidays'),('name', '=', 'hr_leave_rule_employee_unlink')]"/>
|
||||
<value eval="{'noupdate': False}"/>
|
||||
</function>
|
||||
|
||||
|
||||
<record id="hr_holidays.hr_leave_rule_employee_unlink" model="ir.rule">
|
||||
<field name="domain_force">[('employee_id.user_id', '=', user.id), ('state', 'in', ['draft'])]
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -155,6 +155,10 @@
|
|||
<field name="model">hr.leave</field>
|
||||
<field name="inherit_id" ref="hr_holidays.hr_leave_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//form" position="attributes">
|
||||
<attribute name="duplicate">0</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='state']" position="attributes">
|
||||
<attribute name="statusbar_visible">draft,confirm,validate,cancel</attribute>
|
||||
</xpath>
|
||||
|
|
@ -177,8 +181,11 @@
|
|||
<xpath expr="//div[3]/field[@name='request_unit_hours']" position="attributes">
|
||||
<attribute name="readonly">state != 'draft'</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//div[3]" position="inside">
|
||||
<field name="submitted_date" readonly="1" force_save="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='name']" position="attributes">
|
||||
<attribute name="readonly">state != 'draft'</attribute>
|
||||
<attribute name="readonly">state not in ('draft','confirm')</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//label[@for='supported_attachment_ids']" position="attributes">
|
||||
<attribute name="invisible">not leave_type_support_document or state not in ('draft', 'confirm',
|
||||
|
|
@ -195,6 +202,56 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_view_list_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.leave.view.list.inherit</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="inherit_id" ref="hr_holidays.hr_leave_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='date_to']" position="after">
|
||||
<field name="submitted_date" readonly="1" force_save="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//list" position="attributes">
|
||||
<attribute name="duplicate">0</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="view_hr_holidays_filter_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.filter.inherit</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="inherit_id" ref="hr_holidays.view_hr_holidays_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='waiting_for_me_manager']" position="attributes">
|
||||
<attribute name="domain">[
|
||||
('state', 'in', ['confirm', 'validate1']),
|
||||
('employee_id.user_id', '!=', uid),
|
||||
'|',
|
||||
'&',
|
||||
('state', '=', 'confirm'),
|
||||
('employee_id.leave_manager_id', '=', uid),
|
||||
'&',
|
||||
('state', '=', 'validate1'),
|
||||
('holiday_status_id.responsible_ids', 'in', uid)
|
||||
]
|
||||
</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_view_form_manager_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.leave.manager.form.inherit</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="inherit_id" ref="hr_holidays.hr_leave_view_form_manager"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='employee_id']" position="attributes">
|
||||
<attribute name="readonly">state in ['cancel', 'refuse', 'validate', 'validate1', 'confirm']</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//form" position="attributes">
|
||||
<attribute name="duplicate">0</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_accrual_level_view_form_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.leave.accrual.level.form.inherit</field>
|
||||
|
|
|
|||
Loading…
Reference in New Issue