[MERGE] hr_holidays: split model hr.holidays and clean code
* Remove unused 'Remaining Leaves' report * Split hr.holidays into hr.leave and hr.leave.allocation * Split/Rename models/views according to guidelines * Remove 'only-used-once' inline methods
This commit is contained in:
@@ -33,7 +33,9 @@ A synchronization with an internal agenda (Meetings of the CRM module) is also p
|
||||
'security/ir.model.access.csv',
|
||||
|
||||
'views/resource_views.xml',
|
||||
'views/hr_holidays_views.xml',
|
||||
'views/hr_leave_type_views.xml',
|
||||
'views/hr_leave_allocation_views.xml',
|
||||
'views/hr_leave_views.xml',
|
||||
'views/hr_views.xml',
|
||||
|
||||
'wizard/hr_holidays_summary_department_views.xml',
|
||||
@@ -41,8 +43,7 @@ A synchronization with an internal agenda (Meetings of the CRM module) is also p
|
||||
|
||||
'report/hr_holidays_templates.xml',
|
||||
'report/hr_holidays_reports.xml',
|
||||
'report/hr_holidays_leaves_report_views.xml',
|
||||
'report/hr_holidays_views.xml',
|
||||
'report/hr_leave_reports.xml',
|
||||
],
|
||||
'demo': [
|
||||
'data/hr_holidays_demo.xml',
|
||||
|
||||
@@ -7,9 +7,9 @@ from odoo import http
|
||||
|
||||
class HrHolidaysController(http.Controller):
|
||||
|
||||
@http.route('/hr_holidays/validate', type='http', auth='user', methods=['GET'])
|
||||
def hr_holidays_validate(self, res_id, token):
|
||||
comparison, record, redirect = MailController._check_token_and_record_or_redirect('hr.holidays', int(res_id), token)
|
||||
@http.route('/leave/validate', type='http', auth='user', methods=['GET'])
|
||||
def hr_holidays_request_validate(self, res_id, token):
|
||||
comparison, record, redirect = MailController._check_token_and_record_or_redirect('hr.leave', int(res_id), token)
|
||||
if comparison and record:
|
||||
try:
|
||||
record.action_approve()
|
||||
@@ -17,9 +17,29 @@ class HrHolidaysController(http.Controller):
|
||||
return MailController._redirect_to_messaging()
|
||||
return redirect
|
||||
|
||||
@http.route('/hr_holidays/refuse', type='http', auth='user', methods=['GET'])
|
||||
def hr_holidays_refuse(self, res_id, token):
|
||||
comparison, record, redirect = MailController._check_token_and_record_or_redirect('hr.holidays', int(res_id), token)
|
||||
@http.route('/leave/refuse', type='http', auth='user', methods=['GET'])
|
||||
def hr_holidays_request_refuse(self, res_id, token):
|
||||
comparison, record, redirect = MailController._check_token_and_record_or_redirect('hr.leave', int(res_id), token)
|
||||
if comparison and record:
|
||||
try:
|
||||
record.action_refuse()
|
||||
except Exception:
|
||||
return MailController._redirect_to_messaging()
|
||||
return redirect
|
||||
|
||||
@http.route('/allocation/validate', type='http', auth='user', methods=['GET'])
|
||||
def hr_holidays_allocation_validate(self, res_id, token):
|
||||
comparison, record, redirect = MailController._check_token_and_record_or_redirect('hr.leave.allocation', int(res_id), token)
|
||||
if comparison and record:
|
||||
try:
|
||||
record.action_approve()
|
||||
except Exception:
|
||||
return MailController._redirect_to_messaging()
|
||||
return redirect
|
||||
|
||||
@http.route('/allocation/refuse', type='http', auth='user', methods=['GET'])
|
||||
def hr_holidays_allocation_refuse(self, res_id, token):
|
||||
comparison, record, redirect = MailController._check_token_and_record_or_redirect('hr.leave.allocation', int(res_id), token)
|
||||
if comparison and record:
|
||||
try:
|
||||
record.action_refuse()
|
||||
|
||||
@@ -3,93 +3,156 @@
|
||||
<data noupdate="1">
|
||||
|
||||
<!-- Casual leave -->
|
||||
<record id="holiday_status_cl" model="hr.holidays.status">
|
||||
<record id="holiday_status_cl" model="hr.leave.type">
|
||||
<field name="name" eval="'Legal Leaves '+time.strftime('%Y')"/>
|
||||
<field name="limit" eval="False"/>
|
||||
<field name="color_name">black</field>
|
||||
</record>
|
||||
|
||||
<!-- Sick leave -->
|
||||
<record id="holiday_status_sl" model="hr.holidays.status">
|
||||
<record id="holiday_status_sl" model="hr.leave.type">
|
||||
<field name="name">Sick Leaves</field>
|
||||
<field name="limit" eval="True"/>
|
||||
<field name="color_name">red</field>
|
||||
</record>
|
||||
|
||||
<!-- Compensatory Days -->
|
||||
<record id="holiday_status_comp" model="hr.holidays.status">
|
||||
<record id="holiday_status_comp" model="hr.leave.type">
|
||||
<field name="name">Compensatory Days</field>
|
||||
<field name="limit" eval="False"/>
|
||||
<field name="color_name">lavender</field>
|
||||
</record>
|
||||
|
||||
<!--Unpaid Leave -->
|
||||
<record id="holiday_status_unpaid" model="hr.holidays.status">
|
||||
<record id="holiday_status_unpaid" model="hr.leave.type">
|
||||
<field name="name">Unpaid</field>
|
||||
<field name="limit" eval="True"/>
|
||||
<field name="color_name">brown</field>
|
||||
</record>
|
||||
|
||||
<!-- Holidays-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_holidays_confirmed" model="mail.message.subtype">
|
||||
<record id="mt_leave_confirmed" model="mail.message.subtype">
|
||||
<field name="name">Confirmed</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="description">Request created and waiting confirmation</field>
|
||||
</record>
|
||||
|
||||
<record id="mt_holidays_first_validated" model="mail.message.subtype">
|
||||
<record id="mt_leave_first_validated" model="mail.message.subtype">
|
||||
<field name="name">Waiting Second Validation</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Request validated, waiting second validation</field>
|
||||
</record>
|
||||
|
||||
<record id="mt_holidays_approved" model="mail.message.subtype">
|
||||
<record id="mt_leave_approved" model="mail.message.subtype">
|
||||
<field name="name">Approved</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="description">Request approved</field>
|
||||
</record>
|
||||
|
||||
<record id="mt_holidays_refused" model="mail.message.subtype">
|
||||
<record id="mt_leave_refused" model="mail.message.subtype">
|
||||
<field name="name">Refused</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Request refused</field>
|
||||
</record>
|
||||
|
||||
<!-- Allocation-related subtypes for messaging / Chatter -->
|
||||
<record id="mt_leave_allocation_confirmed" model="mail.message.subtype">
|
||||
<field name="name">Confirmed</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="description">Request created and waiting confirmation</field>
|
||||
</record>
|
||||
|
||||
<record id="mt_leave_allocation_first_validated" model="mail.message.subtype">
|
||||
<field name="name">Waiting Second Validation</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Request validated, waiting second validation</field>
|
||||
</record>
|
||||
|
||||
<record id="mt_leave_allocation_approved" model="mail.message.subtype">
|
||||
<field name="name">Approved</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="description">Request approved</field>
|
||||
</record>
|
||||
|
||||
<record id="mt_leave_allocation_refused" model="mail.message.subtype">
|
||||
<field name="name">Refused</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="description">Request refused</field>
|
||||
</record>
|
||||
|
||||
<!-- Department related subtypes for messaging / Chatter -->
|
||||
<record id="mt_department_holidays_confirmed" model="mail.message.subtype">
|
||||
<field name="name">Leaves/Allocations Confirmed</field>
|
||||
<record id="mt_department_leave_confirmed" model="mail.message.subtype">
|
||||
<field name="name">Leaves Confirmed</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="parent_id" eval="ref('mt_holidays_confirmed')"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_confirmed')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="6"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_holidays_first_validated" model="mail.message.subtype">
|
||||
<field name="name">Leaves/Allocations First Approval</field>
|
||||
<record id="mt_department_leave_first_validated" model="mail.message.subtype">
|
||||
<field name="name">Leaves First Approval</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_holidays_first_validated')"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_first_validated')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="7"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_holidays_approved" model="mail.message.subtype">
|
||||
<field name="name">Leaves/Allocation Approved</field>
|
||||
<record id="mt_department_leave_approved" model="mail.message.subtype">
|
||||
<field name="name">Leaves Approved</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_holidays_approved')"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_approved')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="8"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_holidays_refused" model="mail.message.subtype">
|
||||
<field name="name">Leaves/Allocation Refused</field>
|
||||
<record id="mt_department_leave_refused" model="mail.message.subtype">
|
||||
<field name="name">Leaves Refused</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_holidays_refused')"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_refused')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="9"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_leave_allocation_confirmed" model="mail.message.subtype">
|
||||
<field name="name">Allocations Confirmed</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="True"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_allocation_confirmed')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="6"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_leave_allocation_first_validated" model="mail.message.subtype">
|
||||
<field name="name">Allocations First Approval</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_allocation_first_validated')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="7"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_leave_allocation_approved" model="mail.message.subtype">
|
||||
<field name="name">Allocation Approved</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_allocation_approved')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="8"/>
|
||||
</record>
|
||||
|
||||
<record id="mt_department_leave_allocation_refused" model="mail.message.subtype">
|
||||
<field name="name">Allocation Refused</field>
|
||||
<field name="res_model">hr.department</field>
|
||||
<field name="default" eval="False"/>
|
||||
<field name="parent_id" eval="ref('mt_leave_allocation_refused')"/>
|
||||
<field name="relation_field">department_id</field>
|
||||
<field name="sequence" eval="9"/>
|
||||
</record>
|
||||
|
||||
@@ -2,62 +2,53 @@
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="hr_holidays_employee1_allocation_cl" model="hr.holidays">
|
||||
<record id="hr_holidays_employee1_allocation_cl" model="hr.leave.allocation">
|
||||
<field name="name">Legal Leaves for Peter Parker</field>
|
||||
<field name="holiday_status_id" ref="holiday_status_cl"/>
|
||||
<field name="type">add</field>
|
||||
<field name="number_of_days_temp">20</field>
|
||||
<field name="employee_id" ref="hr.employee_root"/>
|
||||
<field name="state">confirm</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_employee1_int_tour" model="hr.holidays">
|
||||
<record id="hr_holidays_employee1_int_tour" model="hr.leave.allocation">
|
||||
<field name="name">International Tour</field>
|
||||
<field name="holiday_status_id" ref="holiday_status_comp"/>
|
||||
<field eval="time.strftime('%Y-%m-26')" name="date_from"/>
|
||||
<field eval="time.strftime('%Y-%m-28')" name="date_to"/>
|
||||
<field name="type">add</field>
|
||||
<field name="number_of_days_temp">7</field>
|
||||
<field name="employee_id" ref="hr.employee_root"/>
|
||||
<field name="state">confirm</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_employee1_vc" model="hr.holidays">
|
||||
<record id="hr_holidays_employee1_vc" model="hr.leave.allocation">
|
||||
<field name="name">Summer Vacation</field>
|
||||
<field name="holiday_status_id" ref="holiday_status_unpaid"/>
|
||||
<field eval="time.strftime('%Y-%m-23')" name="date_from"/>
|
||||
<field eval="time.strftime('%Y-%m-25')" name="date_to"/>
|
||||
<field name="type">add</field>
|
||||
<field name="number_of_days_temp">7</field>
|
||||
<field name="employee_id" ref="hr.employee_root"/>
|
||||
</record>
|
||||
|
||||
<!-- approve the first 2 leave allocations -->
|
||||
<function model="hr.holidays" name="action_approve" eval="[[ref('hr_holidays.hr_holidays_employee1_allocation_cl'), ref('hr_holidays.hr_holidays_employee1_int_tour')]]"/>
|
||||
<function model="hr.leave.allocation" name="action_approve" eval="[[ref('hr_holidays.hr_holidays_employee1_allocation_cl'), ref('hr_holidays.hr_holidays_employee1_int_tour')]]"/>
|
||||
|
||||
<record id="hr_holidays_employee1_cl" model="hr.holidays">
|
||||
<record id="hr_holidays_employee1_cl" model="hr.leave">
|
||||
<field name="name">Trip with Family</field>
|
||||
<field name="holiday_status_id" ref="holiday_status_comp"/>
|
||||
<field eval="time.strftime('%Y-%m-01')" name="date_from"/>
|
||||
<field eval="time.strftime('%Y-%m-03')" name="date_to"/>
|
||||
<field name="type">remove</field>
|
||||
<field name="number_of_days_temp">3</field>
|
||||
<field name="employee_id" ref="hr.employee_root"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_employee1_sl" model="hr.holidays">
|
||||
<record id="hr_holidays_employee1_sl" model="hr.leave">
|
||||
<field name="name">Doctor Appointment</field>
|
||||
<field name="holiday_status_id" ref="holiday_status_sl"/>
|
||||
<field eval="time.strftime('%Y-%m-20')" name="date_from"/>
|
||||
<field eval="time.strftime('%Y-%m-22')" name="date_to"/>
|
||||
<field name="type">remove</field>
|
||||
<field name="number_of_days_temp">3</field>
|
||||
<field name="employee_id" ref="hr.employee_root"/>
|
||||
<field name="state">confirm</field>
|
||||
</record>
|
||||
|
||||
<!-- approve the leave request -->
|
||||
<function model="hr.holidays" name="action_approve" eval="[[ref('hr_holidays.hr_holidays_employee1_sl')]]"/>
|
||||
<function model="hr.leave" name="action_approve" eval="[[ref('hr_holidays.hr_holidays_employee1_sl')]]"/>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -3,4 +3,6 @@
|
||||
|
||||
from . import resource
|
||||
from . import hr
|
||||
from . import hr_holidays
|
||||
from . import hr_leave
|
||||
from . import hr_leave_allocation
|
||||
from . import hr_leave_type
|
||||
|
||||
@@ -23,22 +23,23 @@ class Department(models.Model):
|
||||
|
||||
@api.multi
|
||||
def _compute_leave_count(self):
|
||||
Holiday = self.env['hr.holidays']
|
||||
Requests = self.env['hr.leave']
|
||||
Allocations = self.env['hr.leave.allocation']
|
||||
today_date = datetime.datetime.utcnow().date()
|
||||
today_start = fields.Datetime.to_string(today_date) # get the midnight of the current utc day
|
||||
today_end = fields.Datetime.to_string(today_date + relativedelta(hours=23, minutes=59, seconds=59))
|
||||
|
||||
leave_data = Holiday.read_group(
|
||||
leave_data = Requests.read_group(
|
||||
[('department_id', 'in', self.ids),
|
||||
('state', '=', 'confirm'), ('type', '=', 'remove')],
|
||||
('state', '=', 'confirm')],
|
||||
['department_id'], ['department_id'])
|
||||
allocation_data = Holiday.read_group(
|
||||
allocation_data = Allocations.read_group(
|
||||
[('department_id', 'in', self.ids),
|
||||
('state', '=', 'confirm'), ('type', '=', 'add')],
|
||||
('state', '=', 'confirm')],
|
||||
['department_id'], ['department_id'])
|
||||
absence_data = Holiday.read_group(
|
||||
absence_data = Requests.read_group(
|
||||
[('department_id', 'in', self.ids), ('state', 'not in', ['cancel', 'refuse']),
|
||||
('date_from', '<=', today_end), ('date_to', '>=', today_start), ('type', '=', 'remove')],
|
||||
('date_from', '<=', today_end), ('date_to', '>=', today_start)],
|
||||
['department_id'], ['department_id'])
|
||||
|
||||
res_leave = dict((data['department_id'][0], data['department_id_count']) for data in leave_data)
|
||||
@@ -74,7 +75,7 @@ class Employee(models.Model):
|
||||
('validate', 'Approved'),
|
||||
('cancel', 'Cancelled')
|
||||
])
|
||||
current_leave_id = fields.Many2one('hr.holidays.status', compute='_compute_leave_status', string="Current Leave Type")
|
||||
current_leave_id = fields.Many2one('hr.leave.type', compute='_compute_leave_status', string="Current Leave Type")
|
||||
leave_date_from = fields.Date('From Date', compute='_compute_leave_status')
|
||||
leave_date_to = fields.Date('To Date', compute='_compute_leave_status')
|
||||
leaves_count = fields.Float('Number of Leaves', compute='_compute_leaves_count')
|
||||
@@ -90,8 +91,16 @@ class Employee(models.Model):
|
||||
sum(h.number_of_days) AS days,
|
||||
h.employee_id
|
||||
FROM
|
||||
hr_holidays h
|
||||
join hr_holidays_status s ON (s.id=h.holiday_status_id)
|
||||
(
|
||||
SELECT holiday_status_id, number_of_days,
|
||||
state, employee_id
|
||||
FROM hr_leave_allocation
|
||||
UNION
|
||||
SELECT holiday_status_id, number_of_days,
|
||||
state, employee_id
|
||||
FROM hr_leave
|
||||
) h
|
||||
join hr_leave_type s ON (s.id=h.holiday_status_id)
|
||||
WHERE
|
||||
h.state='validate' AND
|
||||
s.limit=False AND
|
||||
@@ -107,7 +116,7 @@ class Employee(models.Model):
|
||||
|
||||
@api.multi
|
||||
def _inverse_remaining_leaves(self):
|
||||
status_list = self.env['hr.holidays.status'].search([('limit', '=', False)])
|
||||
status_list = self.env['hr.leave.type'].search([('limit', '=', False)])
|
||||
# Create leaves (adding remaining leaves) or raise (reducing remaining leaves)
|
||||
actual_remaining = self._get_remaining_leaves()
|
||||
for employee in self.filtered(lambda employee: employee.remaining_leaves):
|
||||
@@ -125,11 +134,10 @@ class Employee(models.Model):
|
||||
# if a status is found, then compute remaing leave for current employee
|
||||
difference = employee.remaining_leaves - actual_remaining.get(employee.id, 0)
|
||||
if difference > 0:
|
||||
leave = self.env['hr.holidays'].create({
|
||||
leave = self.env['hr.leave.allocation'].create({
|
||||
'name': _('Allocation for %s') % employee.name,
|
||||
'employee_id': employee.id,
|
||||
'holiday_status_id': status.id,
|
||||
'type': 'add',
|
||||
'holiday_type': 'employee',
|
||||
'number_of_days_temp': difference
|
||||
})
|
||||
@@ -142,11 +150,10 @@ class Employee(models.Model):
|
||||
@api.multi
|
||||
def _compute_leave_status(self):
|
||||
# Used SUPERUSER_ID to forcefully get status of other user's leave, to bypass record rule
|
||||
holidays = self.env['hr.holidays'].sudo().search([
|
||||
holidays = self.env['hr.leave'].sudo().search([
|
||||
('employee_id', 'in', self.ids),
|
||||
('date_from', '<=', fields.Datetime.now()),
|
||||
('date_to', '>=', fields.Datetime.now()),
|
||||
('type', '=', 'remove'),
|
||||
('state', 'not in', ('cancel', 'refuse'))
|
||||
])
|
||||
leave_data = {}
|
||||
@@ -165,12 +172,12 @@ class Employee(models.Model):
|
||||
|
||||
@api.multi
|
||||
def _compute_leaves_count(self):
|
||||
leaves = self.env['hr.holidays'].read_group([
|
||||
all_leaves = self.env['hr.leave.report'].read_group([
|
||||
('employee_id', 'in', self.ids),
|
||||
('holiday_status_id.limit', '=', False),
|
||||
('state', '=', 'validate')
|
||||
], fields=['number_of_days', 'employee_id'], groupby=['employee_id'])
|
||||
mapping = dict([(leave['employee_id'][0], leave['number_of_days']) for leave in leaves])
|
||||
mapping = dict([(leave['employee_id'][0], leave['number_of_days']) for leave in all_leaves])
|
||||
for employee in self:
|
||||
employee.leaves_count = mapping.get(employee.id)
|
||||
|
||||
@@ -188,12 +195,11 @@ class Employee(models.Model):
|
||||
today_date = datetime.datetime.utcnow().date()
|
||||
today_start = fields.Datetime.to_string(today_date) # get the midnight of the current utc day
|
||||
today_end = fields.Datetime.to_string(today_date + relativedelta(hours=23, minutes=59, seconds=59))
|
||||
data = self.env['hr.holidays'].read_group([
|
||||
data = self.env['hr.leave'].read_group([
|
||||
('employee_id', 'in', self.ids),
|
||||
('state', 'not in', ['cancel', 'refuse']),
|
||||
('date_from', '<=', today_end),
|
||||
('date_to', '>=', today_start),
|
||||
('type', '=', 'remove')
|
||||
('date_to', '>=', today_start)
|
||||
], ['employee_id'], ['employee_id'])
|
||||
result = dict.fromkeys(self.ids, False)
|
||||
for item in data:
|
||||
@@ -207,11 +213,10 @@ class Employee(models.Model):
|
||||
today_date = datetime.datetime.utcnow().date()
|
||||
today_start = fields.Datetime.to_string(today_date) # get the midnight of the current utc day
|
||||
today_end = fields.Datetime.to_string(today_date + relativedelta(hours=23, minutes=59, seconds=59))
|
||||
holidays = self.env['hr.holidays'].sudo().search([
|
||||
holidays = self.env['hr.leave'].sudo().search([
|
||||
('employee_id', '!=', False),
|
||||
('state', 'not in', ['cancel', 'refuse']),
|
||||
('date_from', '<=', today_end),
|
||||
('date_to', '>=', today_start),
|
||||
('type', '=', 'remove')
|
||||
('date_to', '>=', today_start)
|
||||
])
|
||||
return [('id', 'in', holidays.mapped('employee_id').ids)]
|
||||
|
||||
+161
-326
@@ -17,139 +17,10 @@ _logger = logging.getLogger(__name__)
|
||||
|
||||
HOURS_PER_DAY = 8
|
||||
|
||||
|
||||
class HolidaysType(models.Model):
|
||||
_name = "hr.holidays.status"
|
||||
_description = "Leave Type"
|
||||
|
||||
name = fields.Char('Leave Type', required=True, translate=True)
|
||||
categ_id = fields.Many2one('calendar.event.type', string='Meeting Type',
|
||||
help='Once a leave is validated, Odoo will create a corresponding meeting of this type in the calendar.')
|
||||
color_name = fields.Selection([
|
||||
('red', 'Red'),
|
||||
('blue', 'Blue'),
|
||||
('lightgreen', 'Light Green'),
|
||||
('lightblue', 'Light Blue'),
|
||||
('lightyellow', 'Light Yellow'),
|
||||
('magenta', 'Magenta'),
|
||||
('lightcyan', 'Light Cyan'),
|
||||
('black', 'Black'),
|
||||
('lightpink', 'Light Pink'),
|
||||
('brown', 'Brown'),
|
||||
('violet', 'Violet'),
|
||||
('lightcoral', 'Light Coral'),
|
||||
('lightsalmon', 'Light Salmon'),
|
||||
('lavender', 'Lavender'),
|
||||
('wheat', 'Wheat'),
|
||||
('ivory', 'Ivory')], string='Color in Report', required=True, default='red',
|
||||
help='This color will be used in the leaves summary located in Reporting > Leaves by Department.')
|
||||
limit = fields.Boolean('Allow to Override Limit',
|
||||
help='If you select this check box, the system allows the employees to take more leaves '
|
||||
'than the available ones for this type and will not take them into account for the '
|
||||
'"Remaining Legal Leaves" defined on the employee form.')
|
||||
active = fields.Boolean('Active', default=True,
|
||||
help="If the active field is set to false, it will allow you to hide the leave type without removing it.")
|
||||
|
||||
max_leaves = fields.Float(compute='_compute_leaves', string='Maximum Allowed',
|
||||
help='This value is given by the sum of all leaves requests with a positive value.')
|
||||
leaves_taken = fields.Float(compute='_compute_leaves', string='Leaves Already Taken',
|
||||
help='This value is given by the sum of all leaves requests with a negative value.')
|
||||
remaining_leaves = fields.Float(compute='_compute_leaves', string='Remaining Leaves',
|
||||
help='Maximum Leaves Allowed - Leaves Already Taken')
|
||||
virtual_remaining_leaves = fields.Float(compute='_compute_leaves', string='Virtual Remaining Leaves',
|
||||
help='Maximum Leaves Allowed - Leaves Already Taken - Leaves Waiting Approval')
|
||||
|
||||
double_validation = fields.Boolean(string='Apply Double Validation',
|
||||
help="When selected, the Allocation/Leave Requests for this type require a second validation to be approved.")
|
||||
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id)
|
||||
|
||||
@api.multi
|
||||
def get_days(self, employee_id):
|
||||
# need to use `dict` constructor to create a dict per id
|
||||
result = dict((id, dict(max_leaves=0, leaves_taken=0, remaining_leaves=0, virtual_remaining_leaves=0)) for id in self.ids)
|
||||
|
||||
holidays = self.env['hr.holidays'].search([
|
||||
('employee_id', '=', employee_id),
|
||||
('state', 'in', ['confirm', 'validate1', 'validate']),
|
||||
('holiday_status_id', 'in', self.ids)
|
||||
])
|
||||
|
||||
for holiday in holidays:
|
||||
status_dict = result[holiday.holiday_status_id.id]
|
||||
if holiday.type == 'add':
|
||||
if holiday.state == 'validate':
|
||||
# note: add only validated allocation even for the virtual
|
||||
# count; otherwise pending then refused allocation allow
|
||||
# the employee to create more leaves than possible
|
||||
status_dict['virtual_remaining_leaves'] += holiday.number_of_days_temp
|
||||
status_dict['max_leaves'] += holiday.number_of_days_temp
|
||||
status_dict['remaining_leaves'] += holiday.number_of_days_temp
|
||||
elif holiday.type == 'remove': # number of days is negative
|
||||
status_dict['virtual_remaining_leaves'] -= holiday.number_of_days_temp
|
||||
if holiday.state == 'validate':
|
||||
status_dict['leaves_taken'] += holiday.number_of_days_temp
|
||||
status_dict['remaining_leaves'] -= holiday.number_of_days_temp
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def _compute_leaves(self):
|
||||
data_days = {}
|
||||
if 'employee_id' in self._context:
|
||||
employee_id = self._context['employee_id']
|
||||
else:
|
||||
employee_id = self.env['hr.employee'].search([('user_id', '=', self.env.user.id)], limit=1).id
|
||||
|
||||
if employee_id:
|
||||
data_days = self.get_days(employee_id)
|
||||
|
||||
for holiday_status in self:
|
||||
result = data_days.get(holiday_status.id, {})
|
||||
holiday_status.max_leaves = result.get('max_leaves', 0)
|
||||
holiday_status.leaves_taken = result.get('leaves_taken', 0)
|
||||
holiday_status.remaining_leaves = result.get('remaining_leaves', 0)
|
||||
holiday_status.virtual_remaining_leaves = result.get('virtual_remaining_leaves', 0)
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
if not self._context.get('employee_id'):
|
||||
# leave counts is based on employee_id, would be inaccurate if not based on correct employee
|
||||
return super(HolidaysType, self).name_get()
|
||||
res = []
|
||||
for record in self:
|
||||
name = record.name
|
||||
if not record.limit:
|
||||
name = "%(name)s (%(count)s)" % {
|
||||
'name': name,
|
||||
'count': _('%g remaining out of %g') % (record.virtual_remaining_leaves or 0.0, record.max_leaves or 0.0)
|
||||
}
|
||||
res.append((record.id, name))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
|
||||
""" Override _search to order the results, according to some employee.
|
||||
The order is the following
|
||||
|
||||
- limit (limited leaves first, such as Legal Leaves)
|
||||
- virtual remaining leaves (higher the better, so using reverse on sorted)
|
||||
|
||||
This override is necessary because those fields are not stored and depends
|
||||
on an employee_id given in context. This sort will be done when there
|
||||
is an employee_id in context and that no other order has been given
|
||||
to the method.
|
||||
"""
|
||||
leave_ids = super(HolidaysType, self)._search(args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)
|
||||
if not count and not order and self._context.get('employee_id'):
|
||||
leaves = self.browse(leave_ids)
|
||||
sort_key = lambda l: (not l.limit, l.virtual_remaining_leaves)
|
||||
return leaves.sorted(key=sort_key, reverse=True).ids
|
||||
return leave_ids
|
||||
|
||||
|
||||
class Holidays(models.Model):
|
||||
_name = "hr.holidays"
|
||||
class HolidaysRequest(models.Model):
|
||||
_name = "hr.leave"
|
||||
_description = "Leave"
|
||||
_order = "type desc, date_from desc"
|
||||
_order = "date_from desc"
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
def _default_employee(self):
|
||||
@@ -172,11 +43,11 @@ class Holidays(models.Model):
|
||||
help='Green this button when the leave has been taken into account in the payslip.')
|
||||
report_note = fields.Text('HR Comments')
|
||||
user_id = fields.Many2one('res.users', string='User', related='employee_id.user_id', related_sudo=True, store=True, default=lambda self: self.env.uid, readonly=True)
|
||||
date_from = fields.Datetime('Start Date', readonly=True, index=True, copy=False,
|
||||
date_from = fields.Datetime('Start Date', readonly=True, index=True, copy=False, required=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange')
|
||||
date_to = fields.Datetime('End Date', readonly=True, copy=False,
|
||||
date_to = fields.Datetime('End Date', readonly=True, copy=False, required=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange')
|
||||
holiday_status_id = fields.Many2one("hr.holidays.status", string="Leave Type", required=True, readonly=True,
|
||||
holiday_status_id = fields.Many2one("hr.leave.type", string="Leave Type", required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee', index=True, readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange')
|
||||
@@ -188,15 +59,9 @@ class Holidays(models.Model):
|
||||
help='Number of days of the leave request according to your working schedule.')
|
||||
number_of_days = fields.Float('Number of Days', compute='_compute_number_of_days', store=True, track_visibility='onchange')
|
||||
meeting_id = fields.Many2one('calendar.event', string='Meeting')
|
||||
type = fields.Selection([
|
||||
('remove', 'Leave Request'),
|
||||
('add', 'Allocation Request')
|
||||
], string='Request Type', required=True, readonly=True, index=True, track_visibility='always', default='remove',
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
|
||||
help="Choose 'Leave Request' if someone wants to take an off-day. "
|
||||
"\nChoose 'Allocation Request' if you want to increase the number of leaves available for someone")
|
||||
parent_id = fields.Many2one('hr.holidays', string='Parent')
|
||||
linked_request_ids = fields.One2many('hr.holidays', 'parent_id', string='Linked Requests')
|
||||
|
||||
parent_id = fields.Many2one('hr.leave', string='Parent')
|
||||
linked_request_ids = fields.One2many('hr.leave', 'parent_id', string='Linked Requests')
|
||||
department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||
category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
|
||||
@@ -214,14 +79,18 @@ class Holidays(models.Model):
|
||||
double_validation = fields.Boolean('Apply Double Validation', related='holiday_status_id.double_validation')
|
||||
can_reset = fields.Boolean('Can reset', compute='_compute_can_reset')
|
||||
|
||||
_sql_constraints = [
|
||||
('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )",
|
||||
"The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
|
||||
('date_check2', "CHECK ((date_from <= date_to))", "The start date must be anterior to the end date."),
|
||||
('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."),
|
||||
]
|
||||
|
||||
@api.multi
|
||||
@api.depends('number_of_days_temp', 'type')
|
||||
@api.depends('number_of_days_temp')
|
||||
def _compute_number_of_days(self):
|
||||
for holiday in self:
|
||||
if holiday.type == 'remove':
|
||||
holiday.number_of_days = -holiday.number_of_days_temp
|
||||
else:
|
||||
holiday.number_of_days = holiday.number_of_days_temp
|
||||
holiday.number_of_days = -holiday.number_of_days_temp
|
||||
|
||||
@api.multi
|
||||
def _compute_can_reset(self):
|
||||
@@ -234,39 +103,6 @@ class Holidays(models.Model):
|
||||
if group_hr_manager in user.groups_id or holiday.employee_id and holiday.employee_id.user_id == user:
|
||||
holiday.can_reset = True
|
||||
|
||||
@api.constrains('date_from', 'date_to')
|
||||
def _check_date(self):
|
||||
for holiday in self:
|
||||
domain = [
|
||||
('date_from', '<=', holiday.date_to),
|
||||
('date_to', '>=', holiday.date_from),
|
||||
('employee_id', '=', holiday.employee_id.id),
|
||||
('id', '!=', holiday.id),
|
||||
('type', '=', holiday.type),
|
||||
('state', 'not in', ['cancel', 'refuse']),
|
||||
]
|
||||
nholidays = self.search_count(domain)
|
||||
if nholidays:
|
||||
raise ValidationError(_('You can not have 2 leaves that overlaps on same day!'))
|
||||
|
||||
@api.constrains('state', 'number_of_days_temp')
|
||||
def _check_holidays(self):
|
||||
for holiday in self:
|
||||
if holiday.holiday_type != 'employee' or holiday.type != 'remove' or not holiday.employee_id or holiday.holiday_status_id.limit:
|
||||
continue
|
||||
leave_days = holiday.holiday_status_id.get_days(holiday.employee_id.id)[holiday.holiday_status_id.id]
|
||||
if float_compare(leave_days['remaining_leaves'], 0, precision_digits=2) == -1 or \
|
||||
float_compare(leave_days['virtual_remaining_leaves'], 0, precision_digits=2) == -1:
|
||||
raise ValidationError(_('The number of remaining leaves is not sufficient for this leave type.\n'
|
||||
'Please verify also the leaves waiting for validation.'))
|
||||
|
||||
_sql_constraints = [
|
||||
('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )",
|
||||
"The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
|
||||
('date_check2', "CHECK ( (type='add') OR (date_from <= date_to))", "The start date must be anterior to the end date."),
|
||||
('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."),
|
||||
]
|
||||
|
||||
@api.onchange('holiday_type')
|
||||
def _onchange_type(self):
|
||||
if self.holiday_type == 'employee' and not self.employee_id:
|
||||
@@ -285,18 +121,6 @@ class Holidays(models.Model):
|
||||
if self.holiday_type == 'employee':
|
||||
self.department_id = self.employee_id.department_id
|
||||
|
||||
def _get_number_of_days(self, date_from, date_to, employee_id):
|
||||
""" Returns a float equals to the timedelta between two dates given as string."""
|
||||
from_dt = fields.Datetime.from_string(date_from)
|
||||
to_dt = fields.Datetime.from_string(date_to)
|
||||
|
||||
if employee_id:
|
||||
employee = self.env['hr.employee'].browse(employee_id)
|
||||
return employee.get_work_days_count(from_dt, to_dt)
|
||||
|
||||
time_delta = to_dt - from_dt
|
||||
return math.ceil(time_delta.days + float(time_delta.seconds) / 86400)
|
||||
|
||||
@api.onchange('date_from')
|
||||
def _onchange_date_from(self):
|
||||
""" If there are no date set for date_to, automatically set one 8 hours later than
|
||||
@@ -328,6 +152,43 @@ class Holidays(models.Model):
|
||||
else:
|
||||
self.number_of_days_temp = 0
|
||||
|
||||
@api.constrains('date_from', 'date_to')
|
||||
def _check_date(self):
|
||||
for holiday in self:
|
||||
domain = [
|
||||
('date_from', '<=', holiday.date_to),
|
||||
('date_to', '>=', holiday.date_from),
|
||||
('employee_id', '=', holiday.employee_id.id),
|
||||
('id', '!=', holiday.id),
|
||||
('state', 'not in', ['cancel', 'refuse']),
|
||||
]
|
||||
nholidays = self.search_count(domain)
|
||||
if nholidays:
|
||||
raise ValidationError(_('You can not have 2 leaves that overlaps on same day!'))
|
||||
|
||||
@api.constrains('state', 'number_of_days_temp')
|
||||
def _check_holidays(self):
|
||||
for holiday in self:
|
||||
if holiday.holiday_type != 'employee' or not holiday.employee_id or holiday.holiday_status_id.limit:
|
||||
continue
|
||||
leave_days = holiday.holiday_status_id.get_days(holiday.employee_id.id)[holiday.holiday_status_id.id]
|
||||
if float_compare(leave_days['remaining_leaves'], 0, precision_digits=2) == -1 or \
|
||||
float_compare(leave_days['virtual_remaining_leaves'], 0, precision_digits=2) == -1:
|
||||
raise ValidationError(_('The number of remaining leaves is not sufficient for this leave type.\n'
|
||||
'Please verify also the leaves waiting for validation.'))
|
||||
|
||||
def _get_number_of_days(self, date_from, date_to, employee_id):
|
||||
""" Returns a float equals to the timedelta between two dates given as string."""
|
||||
from_dt = fields.Datetime.from_string(date_from)
|
||||
to_dt = fields.Datetime.from_string(date_to)
|
||||
|
||||
if employee_id:
|
||||
employee = self.env['hr.employee'].browse(employee_id)
|
||||
return employee.get_work_days_count(from_dt, to_dt)
|
||||
|
||||
time_delta = to_dt - from_dt
|
||||
return math.ceil(time_delta.days + float(time_delta.seconds) / 86400)
|
||||
|
||||
####################################################
|
||||
# ORM Overrides methods
|
||||
####################################################
|
||||
@@ -336,20 +197,12 @@ class Holidays(models.Model):
|
||||
def name_get(self):
|
||||
res = []
|
||||
for leave in self:
|
||||
if leave.type == 'remove':
|
||||
if self.env.context.get('short_name'):
|
||||
res.append((leave.id, _("%s : %.2f day(s)") % (leave.name or leave.holiday_status_id.name, leave.number_of_days_temp)))
|
||||
else:
|
||||
res.append((leave.id, _("%s on %s : %.2f day(s)") % (leave.employee_id.name or leave.category_id.name, leave.holiday_status_id.name, leave.number_of_days_temp)))
|
||||
if self.env.context.get('short_name'):
|
||||
res.append((leave.id, _("%s : %.2f day(s)") % (leave.name or leave.holiday_status_id.name, leave.number_of_days_temp)))
|
||||
else:
|
||||
res.append((leave.id, _("Allocation of %s : %.2f day(s) To %s") % (leave.holiday_status_id.name, leave.number_of_days_temp, leave.employee_id.name)))
|
||||
res.append((leave.id, _("%s on %s : %.2f day(s)") % (leave.employee_id.name or leave.category_id.name, leave.holiday_status_id.name, leave.number_of_days_temp)))
|
||||
return res
|
||||
|
||||
def _check_state_access_right(self, vals):
|
||||
if vals.get('state') and vals['state'] not in ['draft', 'confirm', 'cancel'] and not self.env['res.users'].has_group('hr_holidays.group_hr_holidays_user'):
|
||||
return False
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def add_follower(self, employee_id):
|
||||
employee = self.env['hr.employee'].browse(employee_id)
|
||||
@@ -360,20 +213,16 @@ class Holidays(models.Model):
|
||||
def create(self, values):
|
||||
""" Override to avoid automatic logging of creation """
|
||||
employee_id = values.get('employee_id', False)
|
||||
if not self._check_state_access_right(values):
|
||||
raise AccessError(_('You cannot set a leave request as \'%s\'. Contact a human resource manager.') % values.get('state'))
|
||||
if not values.get('department_id'):
|
||||
values.update({'department_id': self.env['hr.employee'].browse(employee_id).department_id.id})
|
||||
holiday = super(Holidays, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values)
|
||||
holiday = super(HolidaysRequest, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values)
|
||||
holiday.add_follower(employee_id)
|
||||
return holiday
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
employee_id = values.get('employee_id', False)
|
||||
if not self._check_state_access_right(values):
|
||||
raise AccessError(_('You cannot set a leave request as \'%s\'. Contact a human resource manager.') % values.get('state'))
|
||||
result = super(Holidays, self).write(values)
|
||||
result = super(HolidaysRequest, self).write(values)
|
||||
self.add_follower(employee_id)
|
||||
return result
|
||||
|
||||
@@ -381,7 +230,7 @@ class Holidays(models.Model):
|
||||
def unlink(self):
|
||||
for holiday in self.filtered(lambda holiday: holiday.state not in ['draft', 'cancel', 'confirm']):
|
||||
raise UserError(_('You cannot delete a leave which is in %s state.') % (holiday.state,))
|
||||
return super(Holidays, self).unlink()
|
||||
return super(HolidaysRequest, self).unlink()
|
||||
|
||||
@api.multi
|
||||
def copy_data(self, default=None):
|
||||
@@ -410,105 +259,10 @@ class Holidays(models.Model):
|
||||
""" This method will create entry in resource calendar leave object at the time of holidays cancel/removed """
|
||||
return self.env['resource.calendar.leaves'].search([('holiday_id', 'in', self.ids)]).unlink()
|
||||
|
||||
@api.multi
|
||||
def action_draft(self):
|
||||
for holiday in self:
|
||||
if not holiday.can_reset:
|
||||
raise UserError(_('Only an HR Manager or the concerned employee can reset to draft.'))
|
||||
if holiday.state not in ['confirm', 'refuse']:
|
||||
raise UserError(_('Leave request state must be "Refused" or "To Approve" in order to reset to Draft.'))
|
||||
holiday.write({
|
||||
'state': 'draft',
|
||||
'first_approver_id': False,
|
||||
'second_approver_id': False,
|
||||
})
|
||||
linked_requests = holiday.mapped('linked_request_ids')
|
||||
for linked_request in linked_requests:
|
||||
linked_request.action_draft()
|
||||
linked_requests.unlink()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
if self.filtered(lambda holiday: holiday.state != 'draft'):
|
||||
raise UserError(_('Leave request must be in Draft state ("To Submit") in order to confirm it.'))
|
||||
return self.write({'state': 'confirm'})
|
||||
|
||||
@api.multi
|
||||
def _check_security_action_approve(self):
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can approve leave requests.'))
|
||||
|
||||
@api.multi
|
||||
def action_approve(self):
|
||||
# if double_validation: this method is the first approval approval
|
||||
# if not double_validation: this method calls action_validate() below
|
||||
self._check_security_action_approve()
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
if any(holiday.state != 'confirm' for holiday in self):
|
||||
raise UserError(_('Leave request must be confirmed ("To Approve") in order to approve it.'))
|
||||
|
||||
self.filtered(lambda hol: hol.double_validation).write({'state': 'validate1', 'first_approver_id': current_employee.id})
|
||||
self.filtered(lambda hol: not hol.double_validation).action_validate()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _prepare_holiday_values(self, employee):
|
||||
self.ensure_one()
|
||||
values = {
|
||||
'name': self.name,
|
||||
'type': self.type,
|
||||
'holiday_type': 'employee',
|
||||
'holiday_status_id': self.holiday_status_id.id,
|
||||
'date_from': self.date_from,
|
||||
'date_to': self.date_to,
|
||||
'notes': self.notes,
|
||||
'number_of_days_temp': self.number_of_days_temp,
|
||||
'parent_id': self.id,
|
||||
'employee_id': employee.id
|
||||
}
|
||||
return values
|
||||
|
||||
@api.multi
|
||||
def _check_security_action_validate(self):
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can approve leave requests.'))
|
||||
|
||||
@api.multi
|
||||
def action_validate(self):
|
||||
self._check_security_action_validate()
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
for holiday in self:
|
||||
if holiday.state not in ['confirm', 'validate1']:
|
||||
raise UserError(_('Leave request must be confirmed in order to approve it.'))
|
||||
if holiday.state == 'validate1' and not holiday.env.user.has_group('hr_holidays.group_hr_holidays_manager'):
|
||||
raise UserError(_('Only an HR Manager can apply the second approval on leave requests.'))
|
||||
|
||||
holiday.write({'state': 'validate'})
|
||||
if holiday.double_validation:
|
||||
holiday.write({'second_approver_id': current_employee.id})
|
||||
else:
|
||||
holiday.write({'first_approver_id': current_employee.id})
|
||||
if holiday.holiday_type == 'employee' and holiday.type == 'remove':
|
||||
holiday._validate_leave_request()
|
||||
elif holiday.holiday_type in ['category', 'department']:
|
||||
leaves = self.env['hr.holidays']
|
||||
employees = holiday.category_id.employee_ids if holiday.holiday_type == 'category' else holiday.department_id.member_ids
|
||||
for employee in employees:
|
||||
values = holiday._prepare_holiday_values(employee)
|
||||
leaves += self.with_context(mail_notify_force_send=False).create(values)
|
||||
# TODO is it necessary to interleave the calls?
|
||||
leaves.action_approve()
|
||||
if leaves and leaves[0].double_validation:
|
||||
leaves.action_validate()
|
||||
return True
|
||||
|
||||
def _validate_leave_request(self):
|
||||
""" Validate leave requests (holiday_type='employee' and holiday.type='remove')
|
||||
""" Validate leave requests (holiday_type='employee')
|
||||
by creating a calendar event and a resource leaves. """
|
||||
for holiday in self.filtered(lambda request: request.type == 'remove' and request.holiday_type == 'employee'):
|
||||
for holiday in self.filtered(lambda request: request.holiday_type == 'employee'):
|
||||
meeting_values = holiday._prepare_holidays_meeting_values()
|
||||
meeting = self.env['calendar.event'].with_context(no_mail_to_attendees=True).create(meeting_values)
|
||||
holiday.write({'meeting_id': meeting.id})
|
||||
@@ -536,9 +290,96 @@ class Holidays(models.Model):
|
||||
(4, self.user_id.partner_id.id)]
|
||||
return meeting_values
|
||||
|
||||
@api.multi
|
||||
def _prepare_holiday_values(self, employee):
|
||||
self.ensure_one()
|
||||
values = {
|
||||
'name': self.name,
|
||||
'holiday_type': 'employee',
|
||||
'holiday_status_id': self.holiday_status_id.id,
|
||||
'date_from': self.date_from,
|
||||
'date_to': self.date_to,
|
||||
'notes': self.notes,
|
||||
'number_of_days_temp': self.number_of_days_temp,
|
||||
'parent_id': self.id,
|
||||
'employee_id': employee.id
|
||||
}
|
||||
return values
|
||||
|
||||
@api.multi
|
||||
def action_draft(self):
|
||||
for holiday in self:
|
||||
if not holiday.can_reset:
|
||||
raise UserError(_('Only an HR Manager or the concerned employee can reset to draft.'))
|
||||
if holiday.state not in ['confirm', 'refuse']:
|
||||
raise UserError(_('Leave request state must be "Refused" or "To Approve" in order to reset to Draft.'))
|
||||
holiday.write({
|
||||
'state': 'draft',
|
||||
'first_approver_id': False,
|
||||
'second_approver_id': False,
|
||||
})
|
||||
linked_requests = holiday.mapped('linked_request_ids')
|
||||
for linked_request in linked_requests:
|
||||
linked_request.action_draft()
|
||||
linked_requests.unlink()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
if self.filtered(lambda holiday: holiday.state != 'draft'):
|
||||
raise UserError(_('Leave request must be in Draft state ("To Submit") in order to confirm it.'))
|
||||
return self.write({'state': 'confirm'})
|
||||
|
||||
@api.multi
|
||||
def action_approve(self):
|
||||
# if double_validation: this method is the first approval approval
|
||||
# if not double_validation: this method calls action_validate() below
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can approve leave requests.'))
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
if any(holiday.state != 'confirm' for holiday in self):
|
||||
raise UserError(_('Leave request must be confirmed ("To Approve") in order to approve it.'))
|
||||
|
||||
self.filtered(lambda hol: hol.double_validation).write({'state': 'validate1', 'first_approver_id': current_employee.id})
|
||||
self.filtered(lambda hol: not hol.double_validation).action_validate()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_validate(self):
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can approve leave requests.'))
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
for holiday in self:
|
||||
if holiday.state not in ['confirm', 'validate1']:
|
||||
raise UserError(_('Leave request must be confirmed in order to approve it.'))
|
||||
if holiday.state == 'validate1' and not holiday.env.user.has_group('hr_holidays.group_hr_holidays_manager'):
|
||||
raise UserError(_('Only an HR Manager can apply the second approval on leave requests.'))
|
||||
|
||||
holiday.write({'state': 'validate'})
|
||||
if holiday.double_validation:
|
||||
holiday.write({'second_approver_id': current_employee.id})
|
||||
else:
|
||||
holiday.write({'first_approver_id': current_employee.id})
|
||||
if holiday.holiday_type == 'employee':
|
||||
holiday._validate_leave_request()
|
||||
elif holiday.holiday_type in ['category', 'department']:
|
||||
leaves = self.env['hr.leave']
|
||||
employees = holiday.category_id.employee_ids if holiday.holiday_type == 'category' else holiday.department_id.member_ids
|
||||
for employee in employees:
|
||||
values = holiday._prepare_holiday_values(employee)
|
||||
leaves += self.with_context(mail_notify_force_send=False).create(values)
|
||||
# TODO is it necessary to interleave the calls?
|
||||
leaves.action_approve()
|
||||
if leaves and leaves[0].double_validation:
|
||||
leaves.action_validate()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_refuse(self):
|
||||
self._check_security_action_refuse()
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can refuse leave requests.'))
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
for holiday in self:
|
||||
@@ -557,11 +398,6 @@ class Holidays(models.Model):
|
||||
self._remove_resource_leave()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def _check_security_action_refuse(self):
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can refuse leave requests.'))
|
||||
|
||||
####################################################
|
||||
# Messaging methods
|
||||
####################################################
|
||||
@@ -569,28 +405,28 @@ class Holidays(models.Model):
|
||||
@api.multi
|
||||
def _track_subtype(self, init_values):
|
||||
if 'state' in init_values and self.state == 'validate':
|
||||
return 'hr_holidays.mt_holidays_approved'
|
||||
return 'hr_holidays.mt_leave_approved'
|
||||
elif 'state' in init_values and self.state == 'validate1':
|
||||
return 'hr_holidays.mt_holidays_first_validated'
|
||||
return 'hr_holidays.mt_leave_first_validated'
|
||||
elif 'state' in init_values and self.state == 'confirm':
|
||||
return 'hr_holidays.mt_holidays_confirmed'
|
||||
return 'hr_holidays.mt_leave_confirmed'
|
||||
elif 'state' in init_values and self.state == 'refuse':
|
||||
return 'hr_holidays.mt_holidays_refused'
|
||||
return super(Holidays, self)._track_subtype(init_values)
|
||||
return 'hr_holidays.mt_leave_refused'
|
||||
return super(HolidaysRequest, self)._track_subtype(init_values)
|
||||
|
||||
@api.multi
|
||||
def _notification_recipients(self, message, groups):
|
||||
""" Handle HR users and officers recipients that can validate or refuse holidays
|
||||
directly from email. """
|
||||
groups = super(Holidays, self)._notification_recipients(message, groups)
|
||||
groups = super(HolidaysRequest, self)._notification_recipients(message, groups)
|
||||
|
||||
self.ensure_one()
|
||||
hr_actions = []
|
||||
if self.state == 'confirm':
|
||||
app_action = self._notification_link_helper('controller', controller='/hr_holidays/validate')
|
||||
app_action = self._notification_link_helper('controller', controller='/leave/validate')
|
||||
hr_actions += [{'url': app_action, 'title': _('Approve')}]
|
||||
if self.state in ['confirm', 'validate', 'validate1']:
|
||||
ref_action = self._notification_link_helper('controller', controller='/hr_holidays/refuse')
|
||||
ref_action = self._notification_link_helper('controller', controller='/leave/refuse')
|
||||
hr_actions += [{'url': ref_action, 'title': _('Refuse')}]
|
||||
|
||||
new_group = (
|
||||
@@ -602,9 +438,8 @@ class Holidays(models.Model):
|
||||
|
||||
@api.multi
|
||||
def _message_notification_recipients(self, message, recipients):
|
||||
result = super(Holidays, self)._message_notification_recipients(message, recipients)
|
||||
leave_type = self.env[message.model].browse(message.res_id).type
|
||||
title = _("See Leave") if leave_type == 'remove' else _("See Allocation")
|
||||
result = super(HolidaysRequest, self)._message_notification_recipients(message, recipients)
|
||||
title = _("See Leave")
|
||||
for res in result:
|
||||
if result[res].get('button_access'):
|
||||
result[res]['button_access']['title'] = title
|
||||
@@ -0,0 +1,299 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
# Copyright (c) 2005-2006 Axelor SARL. (http://www.axelor.com)
|
||||
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import UserError, AccessError
|
||||
from odoo.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HolidaysAllocation(models.Model):
|
||||
_name = "hr.leave.allocation"
|
||||
_description = "Allocation"
|
||||
_inherit = ['mail.thread']
|
||||
|
||||
def _default_employee(self):
|
||||
return self.env.context.get('default_employee_id') or self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
|
||||
name = fields.Char('Description')
|
||||
state = fields.Selection([
|
||||
('draft', 'To Submit'),
|
||||
('cancel', 'Cancelled'),
|
||||
('confirm', 'To Approve'),
|
||||
('refuse', 'Refused'),
|
||||
('validate1', 'Second Approval'),
|
||||
('validate', 'Approved')
|
||||
], string='Status', readonly=True, track_visibility='onchange', copy=False, default='confirm',
|
||||
help="The status is set to 'To Submit', when a leave request is created." +
|
||||
"\nThe status is 'To Approve', when leave request is confirmed by user." +
|
||||
"\nThe status is 'Refused', when leave request is refused by manager." +
|
||||
"\nThe status is 'Approved', when leave request is approved by manager.")
|
||||
holiday_status_id = fields.Many2one("hr.leave.type", string="Leave Type", required=True, readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee', index=True, readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange')
|
||||
notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||
number_of_days_temp = fields.Float(
|
||||
'Allocation', copy=False, readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
|
||||
help='Number of days of the leave request according to your working schedule.')
|
||||
number_of_days = fields.Float('Number of Days', compute='_compute_number_of_days', store=True, track_visibility='onchange')
|
||||
parent_id = fields.Many2one('hr.leave.allocation', string='Parent')
|
||||
linked_request_ids = fields.One2many('hr.leave.allocation', 'parent_id', string='Linked Requests')
|
||||
department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
|
||||
category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True,
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
|
||||
holiday_type = fields.Selection([
|
||||
('employee', 'By Employee'),
|
||||
('department', 'By Department'),
|
||||
('category', 'By Employee Tag')
|
||||
], string='Allocation Mode', readonly=True, required=True, default='employee',
|
||||
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
|
||||
help='By Employee: Allocation for individual Employee, By Employee Tag: Allocation for group of employees in category')
|
||||
first_approver_id = fields.Many2one('hr.employee', string='First Approval', readonly=True, copy=False,
|
||||
help='This area is automatically filled by the user who validate the leave', oldname='manager_id')
|
||||
second_approver_id = fields.Many2one('hr.employee', string='Second Approval', readonly=True, copy=False, oldname='manager_id2',
|
||||
help='This area is automaticly filled by the user who validate the leave with second level (If Leave type need second validation)')
|
||||
double_validation = fields.Boolean('Apply Double Validation', related='holiday_status_id.double_validation')
|
||||
can_reset = fields.Boolean('Can reset', compute='_compute_can_reset')
|
||||
|
||||
_sql_constraints = [
|
||||
('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )",
|
||||
"The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
|
||||
('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."),
|
||||
]
|
||||
|
||||
@api.multi
|
||||
@api.depends('number_of_days_temp')
|
||||
def _compute_number_of_days(self):
|
||||
for holiday in self:
|
||||
holiday.number_of_days = holiday.number_of_days_temp
|
||||
|
||||
@api.multi
|
||||
def _compute_can_reset(self):
|
||||
""" User can reset a leave request if it is its own leave request
|
||||
or if he is an Hr Manager.
|
||||
"""
|
||||
user = self.env.user
|
||||
group_hr_manager = self.env.ref('hr_holidays.group_hr_holidays_manager')
|
||||
for holiday in self:
|
||||
if group_hr_manager in user.groups_id or holiday.employee_id and holiday.employee_id.user_id == user:
|
||||
holiday.can_reset = True
|
||||
|
||||
@api.onchange('holiday_type')
|
||||
def _onchange_type(self):
|
||||
if self.holiday_type == 'employee' and not self.employee_id:
|
||||
if self.env.user.employee_ids:
|
||||
self.employee_id = self.env.user.employee_ids[0]
|
||||
elif self.holiday_type == 'department':
|
||||
if self.env.user.employee_ids:
|
||||
self.department_id = self.department_id or self.env.user.employee_ids[0].department_id
|
||||
self.employee_id = None
|
||||
elif self.holiday_type == 'category':
|
||||
self.employee_id = None
|
||||
self.department_id = None
|
||||
|
||||
@api.onchange('employee_id')
|
||||
def _onchange_employee(self):
|
||||
if self.holiday_type == 'employee':
|
||||
self.department_id = self.employee_id.department_id
|
||||
|
||||
####################################################
|
||||
# ORM Overrides methods
|
||||
####################################################
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
res = []
|
||||
for leave in self:
|
||||
res.append((leave.id, _("Allocation of %s : %.2f day(s) To %s") % (leave.holiday_status_id.name, leave.number_of_days_temp, leave.employee_id.name)))
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def add_follower(self, employee_id):
|
||||
employee = self.env['hr.employee'].browse(employee_id)
|
||||
if employee.user_id:
|
||||
self.message_subscribe_users(user_ids=employee.user_id.ids)
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
""" Override to avoid automatic logging of creation """
|
||||
employee_id = values.get('employee_id', False)
|
||||
if not values.get('department_id'):
|
||||
values.update({'department_id': self.env['hr.employee'].browse(employee_id).department_id.id})
|
||||
holiday = super(HolidaysAllocation, self.with_context(mail_create_nolog=True, mail_create_nosubscribe=True)).create(values)
|
||||
holiday.add_follower(employee_id)
|
||||
return holiday
|
||||
|
||||
@api.multi
|
||||
def write(self, values):
|
||||
employee_id = values.get('employee_id', False)
|
||||
result = super(HolidaysAllocation, self).write(values)
|
||||
self.add_follower(employee_id)
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
for holiday in self.filtered(lambda holiday: holiday.state not in ['draft', 'cancel', 'confirm']):
|
||||
raise UserError(_('You cannot delete a leave which is in %s state.') % (holiday.state,))
|
||||
return super(HolidaysAllocation, self).unlink()
|
||||
|
||||
@api.multi
|
||||
def copy_data(self, default=None):
|
||||
raise UserError(_('A leave cannot be duplicated.'))
|
||||
|
||||
####################################################
|
||||
# Business methods
|
||||
####################################################
|
||||
|
||||
@api.multi
|
||||
def _prepare_holiday_values(self, employee):
|
||||
self.ensure_one()
|
||||
values = {
|
||||
'name': self.name,
|
||||
'holiday_type': 'employee',
|
||||
'holiday_status_id': self.holiday_status_id.id,
|
||||
'notes': self.notes,
|
||||
'number_of_days_temp': self.number_of_days_temp,
|
||||
'parent_id': self.id,
|
||||
'employee_id': employee.id
|
||||
}
|
||||
return values
|
||||
|
||||
@api.multi
|
||||
def action_draft(self):
|
||||
for holiday in self:
|
||||
if not holiday.can_reset:
|
||||
raise UserError(_('Only an HR Manager or the concerned employee can reset to draft.'))
|
||||
if holiday.state not in ['confirm', 'refuse']:
|
||||
raise UserError(_('Leave request state must be "Refused" or "To Approve" in order to reset to Draft.'))
|
||||
holiday.write({
|
||||
'state': 'draft',
|
||||
'first_approver_id': False,
|
||||
'second_approver_id': False,
|
||||
})
|
||||
linked_requests = holiday.mapped('linked_request_ids')
|
||||
for linked_request in linked_requests:
|
||||
linked_request.action_draft()
|
||||
linked_requests.unlink()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_confirm(self):
|
||||
if self.filtered(lambda holiday: holiday.state != 'draft'):
|
||||
raise UserError(_('Leave request must be in Draft state ("To Submit") in order to confirm it.'))
|
||||
return self.write({'state': 'confirm'})
|
||||
|
||||
@api.multi
|
||||
def action_approve(self):
|
||||
# if double_validation: this method is the first approval approval
|
||||
# if not double_validation: this method calls action_validate() below
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can approve leave requests.'))
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
if any(holiday.state != 'confirm' for holiday in self):
|
||||
raise UserError(_('Leave request must be confirmed ("To Approve") in order to approve it.'))
|
||||
|
||||
self.filtered(lambda hol: hol.double_validation).write({'state': 'validate1', 'first_approver_id': current_employee.id})
|
||||
self.filtered(lambda hol: not hol.double_validation).action_validate()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_validate(self):
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can approve leave requests.'))
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
for holiday in self:
|
||||
if holiday.state not in ['confirm', 'validate1']:
|
||||
raise UserError(_('Leave request must be confirmed in order to approve it.'))
|
||||
if holiday.state == 'validate1' and not holiday.env.user.has_group('hr_holidays.group_hr_holidays_manager'):
|
||||
raise UserError(_('Only an HR Manager can apply the second approval on leave requests.'))
|
||||
|
||||
holiday.write({'state': 'validate'})
|
||||
if holiday.double_validation:
|
||||
holiday.write({'second_approver_id': current_employee.id})
|
||||
else:
|
||||
holiday.write({'first_approver_id': current_employee.id})
|
||||
if holiday.holiday_type in ['category', 'department']:
|
||||
leaves = self.env['hr.leave.allocation']
|
||||
employees = holiday.category_id.employee_ids if holiday.holiday_type == 'category' else holiday.department_id.member_ids
|
||||
for employee in employees:
|
||||
values = holiday._prepare_holiday_values(employee)
|
||||
leaves += self.with_context(mail_notify_force_send=False).create(values)
|
||||
# TODO is it necessary to interleave the calls?
|
||||
leaves.action_approve()
|
||||
if leaves and leaves[0].double_validation:
|
||||
leaves.action_validate()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
def action_refuse(self):
|
||||
if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'):
|
||||
raise UserError(_('Only an HR Officer or Manager can refuse leave requests.'))
|
||||
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
|
||||
for holiday in self:
|
||||
if holiday.state not in ['confirm', 'validate', 'validate1']:
|
||||
raise UserError(_('Leave request must be confirmed or validated in order to refuse it.'))
|
||||
|
||||
if holiday.state == 'validate1':
|
||||
holiday.write({'state': 'refuse', 'first_approver_id': current_employee.id})
|
||||
else:
|
||||
holiday.write({'state': 'refuse', 'second_approver_id': current_employee.id})
|
||||
# If a category that created several holidays, cancel all related
|
||||
holiday.linked_request_ids.action_refuse()
|
||||
return True
|
||||
|
||||
####################################################
|
||||
# Messaging methods
|
||||
####################################################
|
||||
|
||||
@api.multi
|
||||
def _track_subtype(self, init_values):
|
||||
if 'state' in init_values and self.state == 'validate':
|
||||
return 'hr_holidays.mt_leave_allocation_approved'
|
||||
elif 'state' in init_values and self.state == 'validate1':
|
||||
return 'hr_holidays.mt_leave_allocation_first_validated'
|
||||
elif 'state' in init_values and self.state == 'confirm':
|
||||
return 'hr_holidays.mt_leave_allocation_confirmed'
|
||||
elif 'state' in init_values and self.state == 'refuse':
|
||||
return 'hr_holidays.mt_leave_allocation_refused'
|
||||
return super(HolidaysAllocation, self)._track_subtype(init_values)
|
||||
|
||||
@api.multi
|
||||
def _notification_recipients(self, message, groups):
|
||||
""" Handle HR users and officers recipients that can validate or refuse holidays
|
||||
directly from email. """
|
||||
groups = super(HolidaysAllocation, self)._notification_recipients(message, groups)
|
||||
|
||||
self.ensure_one()
|
||||
hr_actions = []
|
||||
if self.state == 'confirm':
|
||||
app_action = self._notification_link_helper('controller', controller='/allocation/validate')
|
||||
hr_actions += [{'url': app_action, 'title': _('Approve')}]
|
||||
if self.state in ['confirm', 'validate', 'validate1']:
|
||||
ref_action = self._notification_link_helper('controller', controller='/allocation/refuse')
|
||||
hr_actions += [{'url': ref_action, 'title': _('Refuse')}]
|
||||
|
||||
new_group = (
|
||||
'group_hr_holidays_user', lambda partner: bool(partner.user_ids) and any(user.has_group('hr_holidays.group_hr_holidays_user') for user in partner.user_ids), {
|
||||
'actions': hr_actions,
|
||||
})
|
||||
|
||||
return [new_group] + groups
|
||||
|
||||
@api.multi
|
||||
def _message_notification_recipients(self, message, recipients):
|
||||
result = super(HolidaysAllocation, self)._message_notification_recipients(message, recipients)
|
||||
title = _("See Allocation")
|
||||
for res in result:
|
||||
if result[res].get('button_access'):
|
||||
result[res]['button_access']['title'] = title
|
||||
return result
|
||||
@@ -0,0 +1,147 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
# Copyright (c) 2005-2006 Axelor SARL. (http://www.axelor.com)
|
||||
|
||||
import logging
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.tools.translate import _
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HolidaysType(models.Model):
|
||||
_name = "hr.leave.type"
|
||||
_description = "Leave Type"
|
||||
|
||||
name = fields.Char('Leave Type', required=True, translate=True)
|
||||
categ_id = fields.Many2one('calendar.event.type', string='Meeting Type',
|
||||
help='Once a leave is validated, Odoo will create a corresponding meeting of this type in the calendar.')
|
||||
color_name = fields.Selection([
|
||||
('red', 'Red'),
|
||||
('blue', 'Blue'),
|
||||
('lightgreen', 'Light Green'),
|
||||
('lightblue', 'Light Blue'),
|
||||
('lightyellow', 'Light Yellow'),
|
||||
('magenta', 'Magenta'),
|
||||
('lightcyan', 'Light Cyan'),
|
||||
('black', 'Black'),
|
||||
('lightpink', 'Light Pink'),
|
||||
('brown', 'Brown'),
|
||||
('violet', 'Violet'),
|
||||
('lightcoral', 'Light Coral'),
|
||||
('lightsalmon', 'Light Salmon'),
|
||||
('lavender', 'Lavender'),
|
||||
('wheat', 'Wheat'),
|
||||
('ivory', 'Ivory')], string='Color in Report', required=True, default='red',
|
||||
help='This color will be used in the leaves summary located in Reporting > Leaves by Department.')
|
||||
limit = fields.Boolean('Allow to Override Limit',
|
||||
help='If you select this check box, the system allows the employees to take more leaves '
|
||||
'than the available ones for this type and will not take them into account for the '
|
||||
'"Remaining Legal Leaves" defined on the employee form.')
|
||||
active = fields.Boolean('Active', default=True,
|
||||
help="If the active field is set to false, it will allow you to hide the leave type without removing it.")
|
||||
|
||||
max_leaves = fields.Float(compute='_compute_leaves', string='Maximum Allowed',
|
||||
help='This value is given by the sum of all leaves requests with a positive value.')
|
||||
leaves_taken = fields.Float(compute='_compute_leaves', string='Leaves Already Taken',
|
||||
help='This value is given by the sum of all leaves requests with a negative value.')
|
||||
remaining_leaves = fields.Float(compute='_compute_leaves', string='Remaining Leaves',
|
||||
help='Maximum Leaves Allowed - Leaves Already Taken')
|
||||
virtual_remaining_leaves = fields.Float(compute='_compute_leaves', string='Virtual Remaining Leaves',
|
||||
help='Maximum Leaves Allowed - Leaves Already Taken - Leaves Waiting Approval')
|
||||
|
||||
double_validation = fields.Boolean(string='Apply Double Validation',
|
||||
help="When selected, the Allocation/Leave Requests for this type require a second validation to be approved.")
|
||||
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id)
|
||||
|
||||
@api.multi
|
||||
def get_days(self, employee_id):
|
||||
# need to use `dict` constructor to create a dict per id
|
||||
result = dict((id, dict(max_leaves=0, leaves_taken=0, remaining_leaves=0, virtual_remaining_leaves=0)) for id in self.ids)
|
||||
|
||||
requests = self.env['hr.leave'].search([
|
||||
('employee_id', '=', employee_id),
|
||||
('state', 'in', ['confirm', 'validate1', 'validate']),
|
||||
('holiday_status_id', 'in', self.ids)
|
||||
])
|
||||
|
||||
allocations = self.env['hr.leave.allocation'].search([
|
||||
('employee_id', '=', employee_id),
|
||||
('state', 'in', ['confirm', 'validate1', 'validate']),
|
||||
('holiday_status_id', 'in', self.ids)
|
||||
])
|
||||
|
||||
for request in requests:
|
||||
status_dict = result[request.holiday_status_id.id]
|
||||
status_dict['virtual_remaining_leaves'] -= request.number_of_days_temp
|
||||
if request.state == 'validate':
|
||||
status_dict['leaves_taken'] += request.number_of_days_temp
|
||||
status_dict['remaining_leaves'] -= request.number_of_days_temp
|
||||
|
||||
for allocation in allocations:
|
||||
status_dict = result[allocation.holiday_status_id.id]
|
||||
if allocation.state == 'validate':
|
||||
# note: add only validated allocation even for the virtual
|
||||
# count; otherwise pending then refused allocation allow
|
||||
# the employee to create more leaves than possible
|
||||
status_dict['virtual_remaining_leaves'] += allocation.number_of_days_temp
|
||||
status_dict['max_leaves'] += allocation.number_of_days_temp
|
||||
status_dict['remaining_leaves'] += allocation.number_of_days_temp
|
||||
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def _compute_leaves(self):
|
||||
data_days = {}
|
||||
if 'employee_id' in self._context:
|
||||
employee_id = self._context['employee_id']
|
||||
else:
|
||||
employee_id = self.env['hr.employee'].search([('user_id', '=', self.env.user.id)], limit=1).id
|
||||
|
||||
if employee_id:
|
||||
data_days = self.get_days(employee_id)
|
||||
|
||||
for holiday_status in self:
|
||||
result = data_days.get(holiday_status.id, {})
|
||||
holiday_status.max_leaves = result.get('max_leaves', 0)
|
||||
holiday_status.leaves_taken = result.get('leaves_taken', 0)
|
||||
holiday_status.remaining_leaves = result.get('remaining_leaves', 0)
|
||||
holiday_status.virtual_remaining_leaves = result.get('virtual_remaining_leaves', 0)
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
if not self._context.get('employee_id'):
|
||||
# leave counts is based on employee_id, would be inaccurate if not based on correct employee
|
||||
return super(HolidaysType, self).name_get()
|
||||
res = []
|
||||
for record in self:
|
||||
name = record.name
|
||||
if not record.limit:
|
||||
name = "%(name)s (%(count)s)" % {
|
||||
'name': name,
|
||||
'count': _('%g remaining out of %g') % (record.virtual_remaining_leaves or 0.0, record.max_leaves or 0.0)
|
||||
}
|
||||
res.append((record.id, name))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _search(self, args, offset=0, limit=None, order=None, count=False, access_rights_uid=None):
|
||||
""" Override _search to order the results, according to some employee.
|
||||
The order is the following
|
||||
|
||||
- limit (limited leaves first, such as Legal Leaves)
|
||||
- virtual remaining leaves (higher the better, so using reverse on sorted)
|
||||
|
||||
This override is necessary because those fields are not stored and depends
|
||||
on an employee_id given in context. This sort will be done when there
|
||||
is an employee_id in context and that no other order has been given
|
||||
to the method.
|
||||
"""
|
||||
leave_ids = super(HolidaysType, self)._search(args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)
|
||||
if not count and not order and self._context.get('employee_id'):
|
||||
leaves = self.browse(leave_ids)
|
||||
sort_key = lambda l: (not l.limit, l.virtual_remaining_leaves)
|
||||
return leaves.sorted(key=sort_key, reverse=True).ids
|
||||
return leave_ids
|
||||
@@ -9,4 +9,4 @@ class CalendarLeaves(models.Model):
|
||||
_inherit = "resource.calendar.leaves"
|
||||
_description = "Leave Detail"
|
||||
|
||||
holiday_id = fields.Many2one("hr.holidays", string='Leave Request')
|
||||
holiday_id = fields.Many2one("hr.leave", string='Leave Request')
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import holidays_summary_report
|
||||
from . import hr_holidays_leaves_report
|
||||
from . import hr_leave_report
|
||||
|
||||
@@ -19,7 +19,7 @@ class HrHolidaySummaryReport(models.AbstractModel):
|
||||
'end_date': fields.Date.to_string(st_date + relativedelta(days=59)),
|
||||
'holiday_type': 'Confirmed and Approved' if holiday_type == 'both' else holiday_type
|
||||
}
|
||||
|
||||
|
||||
def _date_is_day_off(self, date):
|
||||
return date.weekday() in (calendar.SATURDAY, calendar.SUNDAY,)
|
||||
|
||||
@@ -58,9 +58,9 @@ class HrHolidaySummaryReport(models.AbstractModel):
|
||||
res[index]['color'] = '#ababab'
|
||||
# count and get leave summary details.
|
||||
holiday_type = ['confirm','validate'] if holiday_type == 'both' else ['confirm'] if holiday_type == 'Confirmed' else ['validate']
|
||||
holidays = self.env['hr.holidays'].search([
|
||||
holidays = self.env['hr.leave'].search([
|
||||
('employee_id', '=', empid), ('state', 'in', holiday_type),
|
||||
('type', '=', 'remove'), ('date_from', '<=', str(end_date)),
|
||||
('date_from', '<=', str(end_date)),
|
||||
('date_to', '>=', str(start_date))
|
||||
])
|
||||
for holiday in holidays:
|
||||
@@ -102,7 +102,7 @@ class HrHolidaySummaryReport(models.AbstractModel):
|
||||
|
||||
def _get_holidays_status(self):
|
||||
res = []
|
||||
for holiday in self.env['hr.holidays.status'].search([]):
|
||||
for holiday in self.env['hr.leave.type'].search([]):
|
||||
res.append({'color': holiday.color_name, 'name': holiday.name})
|
||||
return res
|
||||
|
||||
@@ -112,7 +112,7 @@ class HrHolidaySummaryReport(models.AbstractModel):
|
||||
raise UserError(_("Form content is missing, this report cannot be printed."))
|
||||
|
||||
holidays_report = self.env['ir.actions.report']._get_report_from_name('hr_holidays.report_holidayssummary')
|
||||
holidays = self.env['hr.holidays'].browse(self.ids)
|
||||
holidays = self.env['hr.leave'].browse(self.ids)
|
||||
return {
|
||||
'doc_ids': self.ids,
|
||||
'doc_model': holidays_report.model,
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, tools
|
||||
|
||||
|
||||
class HrHolidaysRemainingLeavesUser(models.Model):
|
||||
|
||||
_name = "hr.holidays.remaining.leaves.user"
|
||||
_description = "Total holidays by type"
|
||||
_auto = False
|
||||
|
||||
name = fields.Char('Employee', readonly=True)
|
||||
no_of_leaves = fields.Integer('Remaining leaves', readonly=True)
|
||||
user_id = fields.Many2one('res.users', string='User', readonly=True)
|
||||
leave_type = fields.Char('Leave Type', readonly=True)
|
||||
|
||||
def init(self):
|
||||
tools.drop_view_if_exists(self._cr, 'hr_holidays_remaining_leaves_user')
|
||||
self._cr.execute("""
|
||||
CREATE or REPLACE view hr_holidays_remaining_leaves_user as (
|
||||
SELECT
|
||||
min(hrs.id) as id,
|
||||
rr.name as name,
|
||||
sum(hrs.number_of_days) as no_of_leaves,
|
||||
rr.user_id as user_id,
|
||||
hhs.name as leave_type
|
||||
FROM
|
||||
hr_holidays as hrs, hr_employee as hre,
|
||||
resource_resource as rr,hr_holidays_status as hhs
|
||||
WHERE
|
||||
hrs.employee_id = hre.id and
|
||||
hre.resource_id = rr.id and
|
||||
hhs.id = hrs.holiday_status_id
|
||||
GROUP BY
|
||||
rr.name,rr.user_id,hhs.name
|
||||
)
|
||||
""")
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_hr_holidays_remaining_leaves_user_tree" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.remaining.leaves.user.tree</field>
|
||||
<field name="model">hr.holidays.remaining.leaves.user</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leaves by Type">
|
||||
<field name="name"/>
|
||||
<field name="leave_type"/>
|
||||
<field name="no_of_leaves"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_holidays_remaining_leaves_user_graph" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.remaining.leaves.user.graph</field>
|
||||
<field name="model">hr.holidays.remaining.leaves.user</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Leaves by Type" type="bar" stacked="True">
|
||||
<field name="name" type="row"/>
|
||||
<field name="no_of_leaves" type="measure"/>
|
||||
<field name="leave_type" type="col"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -4,7 +4,20 @@
|
||||
<report
|
||||
id="action_report_holidayssummary"
|
||||
string="Leaves Summary"
|
||||
model="hr.holidays"
|
||||
model="hr.leave"
|
||||
report_type="qweb-pdf"
|
||||
name="hr_holidays.report_holidayssummary"
|
||||
file="hr_holidays.report_holidayssummary"
|
||||
menu="False"/>
|
||||
|
||||
<record id="action_report_holidayssummary" model="ir.actions.report">
|
||||
<field name="paperformat_id" ref="hr_holidays.paperformat_hrsummary"/>
|
||||
</record>
|
||||
|
||||
<report
|
||||
id="action_report_holidayssummary2"
|
||||
string="Leaves Summary"
|
||||
model="hr.leave.allocation"
|
||||
report_type="qweb-pdf"
|
||||
name="hr_holidays.report_holidayssummary"
|
||||
file="hr_holidays.report_holidayssummary"
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="view_holiday_pivot" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.report_pivot</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Leaves Summary">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="type" type="row"/>
|
||||
<field name="date_from" type="col"/>
|
||||
<field name="number_of_days" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_graph" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.report_graph</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Leaves Summary">
|
||||
<field name="employee_id"/>
|
||||
<field name="type"/>
|
||||
<field name="number_of_days" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_available_holidays_report" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Analysis</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,pivot,calendar,form</field>
|
||||
<field name="view_id"></field> <!-- force empty -->
|
||||
<field name="context">{'search_default_leaves':1}</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_window_leave_pivot" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">pivot</field>
|
||||
<field name="view_id" ref="view_holiday_pivot"/>
|
||||
<field name="act_window_id" ref="action_hr_available_holidays_report"/>
|
||||
</record>
|
||||
|
||||
<record id="action_window_leave_graph" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="view_holiday_graph"/>
|
||||
<field name="act_window_id" ref="action_hr_available_holidays_report"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_available_holidays_report_tree"
|
||||
action="action_hr_available_holidays_report"
|
||||
parent="menu_hr_holidays_report" sequence="5"/>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,78 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import fields, models, tools
|
||||
|
||||
|
||||
class LeaveReport(models.Model):
|
||||
|
||||
_name = "hr.leave.report"
|
||||
_auto = False
|
||||
|
||||
employee_id = fields.Many2one('hr.employee', string="Employee", readonly=True)
|
||||
name = fields.Char('Description', readonly=True)
|
||||
number_of_days = fields.Float('Number of Days', readonly=True)
|
||||
type = fields.Selection([
|
||||
('allocation', 'Allocation Request'),
|
||||
('request', 'Leave Request')
|
||||
], string='Request Type', readonly=True)
|
||||
department_id = fields.Many2one('hr.department', string='Department', readonly=True)
|
||||
category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True)
|
||||
holiday_status_id = fields.Many2one("hr.leave.type", string="Leave Type", readonly=True)
|
||||
state = fields.Selection([
|
||||
('draft', 'To Submit'),
|
||||
('cancel', 'Cancelled'),
|
||||
('confirm', 'To Approve'),
|
||||
('refuse', 'Refused'),
|
||||
('validate1', 'Second Approval'),
|
||||
('validate', 'Approved')
|
||||
], string='Status', readonly=True)
|
||||
holiday_type = fields.Selection([
|
||||
('employee', 'By Employee'),
|
||||
('category', 'By Employee Tag')
|
||||
], string='Allocation Mode', readonly=True)
|
||||
date_from = fields.Datetime('Start Date', readonly=True)
|
||||
date_to = fields.Datetime('End Date', readonly=True)
|
||||
payslip_status = fields.Boolean('Reported in last payslips', readonly=True)
|
||||
|
||||
def init(self):
|
||||
tools.drop_view_if_exists(self._cr, 'hr_leave_report')
|
||||
self._cr.execute("""
|
||||
CREATE or REPLACE view hr_leave_report as (
|
||||
SELECT row_number() over(ORDER BY leaves.employee_id) as id,
|
||||
leaves.employee_id as employee_id, leaves.name as name,
|
||||
leaves.number_of_days as number_of_days, leaves.type as type,
|
||||
leaves.category_id as category_id, leaves.department_id as department_id,
|
||||
leaves.holiday_status_id as holiday_status_id, leaves.state as state,
|
||||
leaves.holiday_type as holiday_type, leaves.date_from as date_from,
|
||||
leaves.date_to as date_to, leaves.payslip_status as payslip_status
|
||||
from (select
|
||||
allocation.employee_id as employee_id,
|
||||
allocation.name as name,
|
||||
allocation.number_of_days as number_of_days,
|
||||
allocation.category_id as category_id,
|
||||
allocation.department_id as department_id,
|
||||
allocation.holiday_status_id as holiday_status_id,
|
||||
allocation.state as state,
|
||||
allocation.holiday_type,
|
||||
null as date_from,
|
||||
null as date_to,
|
||||
FALSE as payslip_status,
|
||||
'allocation' as type
|
||||
from hr_leave_allocation as allocation
|
||||
union select
|
||||
request.employee_id as employee_id,
|
||||
request.name as name,
|
||||
request.number_of_days as number_of_days,
|
||||
request.category_id as category_id,
|
||||
request.department_id as department_id,
|
||||
request.holiday_status_id as holiday_status_id,
|
||||
request.state as state,
|
||||
request.holiday_type,
|
||||
request.date_from as date_from,
|
||||
request.date_to as date_to,
|
||||
request.payslip_status as payslip_status,
|
||||
'request' as type
|
||||
from hr_leave as request) leaves
|
||||
);
|
||||
""")
|
||||
@@ -0,0 +1,164 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_hr_holidays_filter_report" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.filter</field>
|
||||
<field name="model">hr.leave.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Leave">
|
||||
<field name="name"/>
|
||||
<filter domain="[('state','in',('confirm','validate1'))]" string="To Approve" name="approve"/>
|
||||
<filter string="Approved Requests" domain="[('state', '=', 'validate')]" name="validated"/>
|
||||
<separator/>
|
||||
<filter name="active_types" string="Active Types" domain="[('holiday_status_id.active', '=', True)]" help="Filters only on requests that belong to an leave type that is 'active' (active field is True)"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<separator/>
|
||||
<filter string="My Department Leaves" name="department" domain="[('department_id.manager_id.user_id', '=', uid)]" help="My Department Leaves"/>
|
||||
<filter name="my_team_leaves" string="My Team Leaves" domain="[('employee_id.parent_id.user_id', '=', uid)]" groups="hr_holidays.group_hr_holidays_manager" help="Leaves of Your Team Member"/>
|
||||
<separator/>
|
||||
<filter string="To Report in Payslip" name="gray" domain="[('payslip_status', '=', False)]" groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
<separator/>
|
||||
<filter string="To Do" name="todo" domain="[('payslip_status', '=', False), ('holiday_status_id.active', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="year" string="Current Year"
|
||||
domain="[('holiday_status_id.active', '=', True)]" help="Active Leaves"/>
|
||||
<separator/>
|
||||
<filter string="My Requests" name="my_leaves" domain="[('employee_id.user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_name" string="Description" context="{'group_by':'name'}"/>
|
||||
<filter name="group_employee" string="Employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter name="group_category" string="Category" context="{'group_by':'category_id'}"/>
|
||||
<filter name="group_manager" string="Manager" context="{'group_by':'manager_id'}"/>
|
||||
<filter name="group_second_approver_id" string="Validator" context="{'group_by':'second_approver_id'}"/>
|
||||
<filter name="group_type" string="Type" context="{'group_by':'holiday_status_id'}"/>
|
||||
<separator/>
|
||||
<filter name="group_date_from" string="Start Month" context="{'group_by':'date_from'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_leave_report_tree" model="ir.ui.view">
|
||||
<field name="name">report.hr.holidays.report.leave_all.tree</field>
|
||||
<field name="model">hr.leave.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree create="0" edit="0" delete="0">
|
||||
<field name="type"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days" string="Number of Days" sum="Remaining Days"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- TODO: See if we need to keep this -->
|
||||
<record id="hr_leave_report_kanban" model="ir.ui.view">
|
||||
<field name="name">report.hr.holidays.report.leave_all.kanban</field>
|
||||
<field name="model">hr.leave.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="o_kanban_mobile" create="0">
|
||||
<field name="employee_id"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click">
|
||||
<div>
|
||||
<span>
|
||||
<img t-att-src="kanban_image('hr.employee', 'image_small', record.employee_id.raw_value)" t-att-title="record.employee_id.value" width="40" height="40" class="oe_kanban_avatar pull-left mr4"/>
|
||||
</span>
|
||||
<span>
|
||||
<div>
|
||||
<strong class="o_kanban_record_title"><t t-esc="record.employee_id.value"/></strong>
|
||||
<span class="pull-right">
|
||||
<field name="state" widget="kanban_label_selection" options="{'classes': {'draft': 'default', 'validate': 'success','confirm': 'default', 'cancel': 'danger'}}"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted o_kanban_record_subtitle">
|
||||
<t t-esc="record.name.value"/>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<hr class="mt4 mb8"/>
|
||||
<div class="o_kanban_record_bottom mt8 mb4">
|
||||
<div t-attf-class="oe_kanban_bottom_left #{record.date_from.value ? 'mt8 mb4': ''}">
|
||||
<table class="text-right" t-if="record.date_from.value">
|
||||
<tr>
|
||||
<td style="padding-bottom:4px"><small class="text-muted">from</small></td>
|
||||
<td style="padding:0 0 4px 4px"><t t-esc="record.date_from.value"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><small class="text-muted">to</small></td>
|
||||
<td style="padding-left:4px"><t t-esc="record.date_to.value"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div t-attf-class="oe_kanban_bottom_right #{record.date_from.value ? 'mt8': ''}">
|
||||
<span class="badge"><t t-esc="record.number_of_days.value"/> days</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="open_company_allocation" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Summary</field>
|
||||
<field name="res_model">hr.leave.report</field>
|
||||
<field name="src_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban</field>
|
||||
<field name="view_id" eval="hr_leave_report_tree"/>
|
||||
<field name="context">{
|
||||
'search_default_group_type': 1,
|
||||
'search_default_year': 1 ,
|
||||
'search_default_my_leaves': 1,
|
||||
'needaction_menu_ref':
|
||||
[
|
||||
'hr_holidays.menu_open_ask_holidays_new',
|
||||
'hr_holidays.menu_open_allocation_holidays',
|
||||
'hr_holidays.menu_request_approve_allocation',
|
||||
'hr_holidays.menu_open_employee_leave',
|
||||
]
|
||||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('holiday_type','=','employee')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter_report"/>
|
||||
</record>
|
||||
|
||||
<record id="act_hr_employee_holiday_request" model="ir.actions.act_window">
|
||||
<field name="name">Leaves</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.leave.report</field>
|
||||
<field name="src_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_employee_id': [active_id], 'default_employee_id': active_id, 'search_default_group_type': 1,
|
||||
'search_default_year': 1}</field>
|
||||
<field name="domain">[('holiday_type','=','employee'), ('holiday_status_id.limit', '=', False), ('state','!=', 'refuse')]</field>
|
||||
<field name="search_view_id" ref="view_hr_leave_allocation_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_company_allocation"
|
||||
name="Leaves Summary"
|
||||
parent="menu_hr_holidays_my_leaves"
|
||||
action="open_company_allocation"
|
||||
sequence="21"/>
|
||||
|
||||
</odoo>
|
||||
@@ -17,9 +17,9 @@
|
||||
<field name="groups_id" eval="[(4,ref('hr_holidays.group_hr_holidays_manager'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="property_rule_holidays_employee" model="ir.rule">
|
||||
<record id="property_rule_request_employee" model="ir.rule">
|
||||
<field name="name">Employee Leaves</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
<field name="model_id" ref="model_hr_leave"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
@@ -27,17 +27,42 @@
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="property_rule_holidays_employee_write" model="ir.rule">
|
||||
<record id="property_rule_request_employee_write" model="ir.rule">
|
||||
<field name="name">Employee Leaves Create, Write, Unlink</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
<field name="model_id" ref="model_hr_leave"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id), ('state', 'in', ['draft', 'confirm', 'cancel', 'refuse'])]</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="property_rule_holidays_officer" model="ir.rule">
|
||||
<record id="property_rule_request_officer" model="ir.rule">
|
||||
<field name="name">Leaves Officer</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
<field name="model_id" ref="model_hr_leave"/>
|
||||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(4,ref('hr_holidays.group_hr_holidays_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="property_rule_allocation_employee" model="ir.rule">
|
||||
<field name="name">Employee Allocations</field>
|
||||
<field name="model_id" ref="model_hr_leave_allocation"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id)]</field>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="property_rule_allocation_employee_write" model="ir.rule">
|
||||
<field name="name">Employee Allocations Create, Write, Unlink</field>
|
||||
<field name="model_id" ref="model_hr_leave_allocation"/>
|
||||
<field name="domain_force">[('employee_id.user_id','=',user.id), ('state', 'in', ['draft', 'confirm', 'cancel', 'refuse'])]</field>
|
||||
<field name="perm_read" eval="False"/>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="property_rule_allocation_officer" model="ir.rule">
|
||||
<field name="name">Leaves Officer</field>
|
||||
<field name="model_id" ref="model_hr_leave_allocation"/>
|
||||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(4,ref('hr_holidays.group_hr_holidays_user'))]"/>
|
||||
</record>
|
||||
@@ -51,7 +76,7 @@
|
||||
|
||||
<record id="hr_holidays_status_rule_multi_company" model="ir.rule">
|
||||
<field name="name">Leaves multi company rule</field>
|
||||
<field name="model_id" ref="model_hr_holidays_status"/>
|
||||
<field name="model_id" ref="model_hr_leave_type"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','in',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_hr_holidays_user,hr.holidays.user,model_hr_holidays,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_hr_holidays_employee,hr.holidays.employee,model_hr_holidays,base.group_user,1,1,1,1
|
||||
access_hr_holydays_status_employee,hr.holidays.status employee,model_hr_holidays_status,base.group_user,1,0,0,0
|
||||
access_hr_holydays_status_manager,hr.holidays.status manager,model_hr_holidays_status,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_hr_holidays_remain_user,hr.holidays.ramain.user,model_hr_holidays_remaining_leaves_user,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_resource_calendar_leaves_user,resource_calendar_leaves_user,resource.model_resource_calendar_leaves,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_calendar_event_hr_user,calendar.event.hr.user,calendar.model_calendar_event,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_calendar_event_type_manager,calendar.event.type.manager,calendar.model_calendar_event_type,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_calendar_attendee_hr_user,calendar.attendee.hr.user,calendar.model_calendar_attendee,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_hr_holidays_user_request,hr.holidays.user.request,model_hr_leave,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_hr_holidays_employee_request,hr.holidays.employee.request,model_hr_leave,base.group_user,1,1,1,1
|
||||
access_hr_holidays_user_allocation,hr.holidays.user.allocation,model_hr_leave_allocation,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_hr_holidays_employee_allocation,hr.holidays.employee.allocation,model_hr_leave_allocation,base.group_user,1,1,1,1
|
||||
access_hr_holidays_status_employee,hr.holidays.status employee,model_hr_leave_type,base.group_user,1,0,0,0
|
||||
access_hr_holidays_status_manager,hr.holidays.status manager,model_hr_leave_type,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_hr_leave_report,access_hr_leave_report,model_hr_leave_report,,1,0,0,0
|
||||
access_resource_calendar_leaves_user,resource_calendar_leaves_user,resource.model_resource_calendar_leaves,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_calendar_event_hr_user,calendar.event.hr.user,calendar.model_calendar_event,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
access_calendar_event_type_manager,calendar.event.type.manager,calendar.model_calendar_event_type,hr_holidays.group_hr_holidays_manager,1,1,1,1
|
||||
access_calendar_attendee_hr_user,calendar.attendee.hr.user,calendar.model_calendar_attendee,hr_holidays.group_hr_holidays_user,1,1,1,1
|
||||
|
||||
|
@@ -14,8 +14,9 @@ class TestHolidaysFlow(TestHrHolidaysBase):
|
||||
@mute_logger('odoo.addons.base.models.ir_model', 'odoo.models')
|
||||
def test_00_leave_request_flow(self):
|
||||
""" Testing leave request flow """
|
||||
Holidays = self.env['hr.holidays']
|
||||
HolidaysStatus = self.env['hr.holidays.status']
|
||||
Requests = self.env['hr.leave']
|
||||
Allocations = self.env['hr.leave.allocation']
|
||||
HolidaysStatus = self.env['hr.leave.type']
|
||||
|
||||
def _check_holidays_status(holiday_status, ml, lt, rl, vrl):
|
||||
self.assertEqual(holiday_status.max_leaves, ml,
|
||||
@@ -56,7 +57,7 @@ class TestHolidaysFlow(TestHrHolidaysBase):
|
||||
# --------------------------------------------------
|
||||
|
||||
# Employee creates a leave request for another employee -> should crash
|
||||
HolidaysEmployeeGroup = Holidays.sudo(self.user_employee_id)
|
||||
HolidaysEmployeeGroup = Requests.sudo(self.user_employee_id)
|
||||
with self.assertRaises(ValidationError):
|
||||
HolidaysEmployeeGroup.create({
|
||||
'name': 'Hol10',
|
||||
@@ -66,7 +67,7 @@ class TestHolidaysFlow(TestHrHolidaysBase):
|
||||
'date_to': datetime.today(),
|
||||
'number_of_days_temp': 1,
|
||||
})
|
||||
Holidays.search([('name', '=', 'Hol10')]).unlink()
|
||||
Requests.search([('name', '=', 'Hol10')]).unlink()
|
||||
|
||||
# Employee creates a leave request in a no-limit category
|
||||
hol1_employee_group = HolidaysEmployeeGroup.create({
|
||||
@@ -110,20 +111,19 @@ class TestHolidaysFlow(TestHrHolidaysBase):
|
||||
'name': 'Hol22',
|
||||
'employee_id': self.employee_emp_id,
|
||||
'holiday_status_id': self.holidays_status_2.id,
|
||||
'date_from': (datetime.today() + relativedelta(days=0)).strftime('%Y-%m-%d %H:%M'),
|
||||
'date_to': (datetime.today() + relativedelta(days=1)),
|
||||
'date_from': (datetime.today() + relativedelta(days=1)).strftime('%Y-%m-%d %H:%M'),
|
||||
'date_to': (datetime.today() + relativedelta(days=2)),
|
||||
'number_of_days_temp': 1,
|
||||
})
|
||||
|
||||
# Clean transaction
|
||||
Holidays.search([('name', 'in', ['Hol21', 'Hol22'])]).unlink()
|
||||
Requests.search([('name', 'in', ['Hol21', 'Hol22'])]).unlink()
|
||||
|
||||
# HrUser allocates some leaves to the employee
|
||||
aloc1_user_group = Holidays.sudo(self.user_hruser_id).create({
|
||||
aloc1_user_group = Allocations.sudo(self.user_hruser_id).create({
|
||||
'name': 'Days for limited category',
|
||||
'employee_id': self.employee_emp_id,
|
||||
'holiday_status_id': self.holidays_status_2.id,
|
||||
'type': 'add',
|
||||
'number_of_days_temp': 2,
|
||||
})
|
||||
# HrUser validates the first step
|
||||
@@ -191,13 +191,12 @@ class TestHolidaysFlow(TestHrHolidaysBase):
|
||||
# cl can be of maximum 20 days for employee_root
|
||||
hol3_status = self.env.ref('hr_holidays.holiday_status_cl').with_context(employee_id=employee_id)
|
||||
# I assign the dates in the holiday request for 1 day
|
||||
hol3 = Holidays.create({
|
||||
hol3 = Requests.create({
|
||||
'name': 'Sick Leave',
|
||||
'holiday_status_id': hol3_status.id,
|
||||
'date_from': datetime.today().strftime('%Y-%m-10 10:00:00'),
|
||||
'date_to': datetime.today().strftime('%Y-%m-11 19:00:00'),
|
||||
'employee_id': employee_id,
|
||||
'type': 'remove',
|
||||
'number_of_days_temp': 1
|
||||
})
|
||||
# I find a small mistake on my leave request to I click on "Refuse" button to correct a mistake.
|
||||
|
||||
@@ -1,798 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<odoo>
|
||||
|
||||
<!-- Graph report -->
|
||||
<record id="view_evaluation_report_graph" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.graph</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Appraisal Analysis" stacked="True">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="holiday_status_id" type="row"/>
|
||||
<field name="date_from" type="col"/>
|
||||
<field name="number_of_days" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_holidays_filter" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.filter</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Leave">
|
||||
<field name="name"/>
|
||||
<filter domain="[('state','in',('confirm','validate1'))]" string="To Approve" name="approve"/>
|
||||
<filter string="Approved Leaves" domain="[('state', '=', 'validate')]" name="validated"/>
|
||||
<separator/>
|
||||
<filter name="active_types" string="Active Types" domain="[('holiday_status_id.active', '=', True)]" help="Filters only on allocations and requests that belong to an leave type that is 'active' (active field is True)"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<separator/>
|
||||
<filter string="My Department Leaves" name="department" domain="[('department_id.manager_id.user_id', '=', uid)]" help="My Department Leaves"/>
|
||||
<filter name="my_team_leaves" string="My Team Leaves" domain="[('employee_id.parent_id.user_id', '=', uid)]" groups="hr_holidays.group_hr_holidays_manager" help="Leaves of Your Team Member"/>
|
||||
<separator/>
|
||||
<filter string="To Report in Payslip" name="gray" domain="[('payslip_status', '=', False)]" groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
<separator/>
|
||||
<filter string="To Do" name="todo" domain="[('payslip_status', '=', False), ('holiday_status_id.active', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="year" string="Current Year"
|
||||
domain="[('holiday_status_id.active', '=', True)]" help="Active Leaves and Allocations"/>
|
||||
<separator/>
|
||||
<filter string="My Leaves" name="my_leaves" domain="[('user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter name="leaves" string="Leaves" domain="[('type', '=', 'remove')]"/>
|
||||
<filter name="allocations" string="Allocations" domain="[('type', '=', 'add')]"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_name" string="Description" context="{'group_by':'name'}"/>
|
||||
<filter name="group_employee" string="Employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter name="group_category" string="Category" context="{'group_by':'category_id'}"/>
|
||||
<filter name="group_manager" string="Manager" context="{'group_by':'manager_id'}"/>
|
||||
<filter name="group_second_approver_id" string="Validator" context="{'group_by':'second_approver_id'}"/>
|
||||
<filter name="group_type" string="Type" context="{'group_by':'holiday_status_id'}"/>
|
||||
<separator/>
|
||||
<filter name="group_date_from" string="Start Month" context="{'group_by':'date_from'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Holidays: Leave Request -->
|
||||
|
||||
<record id="view_holiday_new_calendar" model="ir.ui.view">
|
||||
<field name="name">Leave Request</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Leave Request" date_start="date_from" date_stop="date_to" mode="month" quick_add="False" color="employee_id">
|
||||
<field name="display_name"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Holidays: Allocation Request -->
|
||||
<record id="edit_holiday_new" model="ir.ui.view">
|
||||
<field name="name">Leave Request</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Leave Request">
|
||||
<field name="can_reset" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<header>
|
||||
<button string="Confirm" name="action_confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button string="Approve" name="action_approve" states="confirm" type="object" groups="hr_holidays.group_hr_holidays_user" class="oe_highlight"/>
|
||||
<button string="Validate" name="action_validate" states="validate1" type="object" groups="hr_holidays.group_hr_holidays_manager" class="oe_highlight"/>
|
||||
<button string="Refuse" name="action_refuse" states="confirm,validate,validate1" type="object" groups="hr_holidays.group_hr_holidays_user"/>
|
||||
<button string="Reset to Draft" name="action_draft" type="object"
|
||||
attrs="{'invisible': ['|', ('can_reset', '=', False), ('state', 'not in', ['confirm', 'refuse'])]}"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,validate"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="display_name"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" attrs="{'readonly':[('state','!=','draft'),('state','!=','confirm')]}"/>
|
||||
<field name="holiday_status_id" context="{'employee_id':employee_id}"/>
|
||||
<label for="number_of_days_temp" string="Duration"/>
|
||||
<div>
|
||||
<div attrs="{'invisible': [('type', '=', 'add')]}">
|
||||
<field name="date_from" attrs="{'required':[('type', '=', 'remove')]}" class="oe_inline"/>
|
||||
<label string="-" class="oe_inline"/>
|
||||
<field name="date_to" attrs="{'required':[('type', '=', 'remove')]}" class="oe_inline"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="number_of_days_temp" class="oe_inline"/> days
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="holiday_type" attrs="{'readonly':[('type', '=', 'remove'),('state','!=','draft')]}" string="Mode" groups="hr_holidays.group_hr_holidays_user" context="{'employee_id':employee_id}" />
|
||||
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')],'invisible':[('holiday_type','!=','employee')]}" groups="hr_holidays.group_hr_holidays_user"/>
|
||||
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'readonly': [('type', '=', 'remove'),('state','!=','draft'), ('state','!=','confirm')], 'invisible':[('holiday_type','!=','category')]}"/>
|
||||
<field name="department_id" groups="hr_holidays.group_hr_holidays_user" attrs="{'readonly':['|',('state','=', 'validate'),('holiday_type','!=','department')],'invisible':[('holiday_type','=','category')]}"/>
|
||||
<field name="payslip_status" groups="hr_holidays.group_hr_holidays_manager" attrs="{'invisible':[('type','=','add')]}" widget="toggle_button"/>
|
||||
</group>
|
||||
<field name="notes" nolabel="1" colspan="4" placeholder="Add a reason..." attrs="{'invisible': [('type', '=', 'remove')]}"/>
|
||||
<div groups="hr_holidays.group_hr_holidays_manager" attrs="{'invisible':[('type','=','add')]}">
|
||||
<separator string="Comment by Manager"/>
|
||||
<field name="report_note" placeholder="e.g. Report to the next month..."/>
|
||||
</div>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_allocation_tree" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.allocation.tree</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == 'draft'" string="Allocation Requests"
|
||||
decoration-bf="message_needaction == True">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_view_list_my_allocation" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.my.allocation.tree</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == 'draft'" string="Allocation Requests"
|
||||
decoration-bf="message_needaction == True">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_allocation_tree_customize" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.allocation.tree.customize</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Allocation Requests" editable="top">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_type"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="date_from" required="1"/>
|
||||
<field name="date_to" required="1"/>
|
||||
<field name="number_of_days_temp" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="state"/>
|
||||
<field name="payslip_status" widget="toggle_button" options='{"active": "Reported in last payslips", "inactive": "To Report in Payslip"}' groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
<field name="report_note" groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_simple" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.report_tree</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == 'draft'" string="Leaves Summary">
|
||||
<field name="type"/>
|
||||
<field name="holiday_status_id" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days" string="Number of Days" sum="Remaining Days"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_holidays_kanban" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.kanban</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="o_kanban_mobile">
|
||||
<field name="employee_id"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click">
|
||||
<div>
|
||||
<span>
|
||||
<img t-att-src="kanban_image('hr.employee', 'image_small', record.employee_id.raw_value)" t-att-title="record.employee_id.value" width="40" height="40" class="oe_kanban_avatar pull-left mr4"/>
|
||||
</span>
|
||||
<span>
|
||||
<div>
|
||||
<strong class="o_kanban_record_title"><t t-esc="record.employee_id.value"/></strong>
|
||||
<span class="pull-right">
|
||||
<field name="state" widget="kanban_label_selection" options="{'classes': {'draft': 'default', 'validate': 'success','confirm': 'default', 'cancel': 'danger'}}"/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-muted o_kanban_record_subtitle">
|
||||
<t t-esc="record.name.value"/>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<hr class="mt4 mb8"/>
|
||||
<div class="o_kanban_record_bottom mt8 mb4">
|
||||
<div t-attf-class="oe_kanban_bottom_left #{record.date_from.value ? 'mt8 mb4': ''}">
|
||||
<table class="text-right" t-if="record.date_from.value">
|
||||
<tr>
|
||||
<td style="padding-bottom:4px"><small class="text-muted">from</small></td>
|
||||
<td style="padding:0 0 4px 4px"><t t-esc="record.date_from.value"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><small class="text-muted">to</small></td>
|
||||
<td style="padding-left:4px"><t t-esc="record.date_to.value"/></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div t-attf-class="oe_kanban_bottom_right #{record.date_from.value ? 'mt8': ''}">
|
||||
<span class="badge"><t t-esc="record.number_of_days.value"/> days</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.tree</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == ' draft'" string="Leave Requests"
|
||||
decoration-bf="message_needaction == True">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_type" string="Mode" groups="base.group_no_one"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="number_of_days" string="Number of Days" sum="Remaining Days"/>
|
||||
<field name="state"/>
|
||||
<field name="payslip_status" widget="toggle_button" options='{"active": "Reported in last payslips", "inactive": "To Report in Payslip"}' groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
<field name="category_id" invisible="1"/>
|
||||
<field name="department_id" invisible="not context.get('set_visible',False)"/>
|
||||
<field name="manager_id" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_holidays_dashboard" model="ir.actions.act_window">
|
||||
<field name="name">All Leaves</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="context">{'search_default_year': 1, 'search_default_group_employee': 1}</field>
|
||||
<field name="domain">[('holiday_type','=','employee'), ('type', '=', 'remove'), ('state', '!=', 'refuse')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Leaves"
|
||||
id="menu_hr_holidays_root"
|
||||
sequence="95"
|
||||
web_icon="hr_holidays,static/description/icon.png"
|
||||
groups="base.group_user"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_dashboard"
|
||||
name="Dashboard"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="1"
|
||||
action="action_hr_holidays_dashboard"
|
||||
groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_my_leaves"
|
||||
name="My Leaves"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="2"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_approvals"
|
||||
name="Managers"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="3"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_report"
|
||||
name="Reporting"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="99"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"/>
|
||||
|
||||
<record id="open_ask_holidays" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Request</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="context">{
|
||||
'default_type': 'remove',
|
||||
}</field>
|
||||
<field name="domain">[('type','=','remove'), ('user_id', '=', uid)]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new leave request.
|
||||
</p><p>
|
||||
Once you have recorded your leave request, it will be sent
|
||||
to a manager for validation. Be sure to set the right leave
|
||||
type (recuperation, legal leaves, sickness) and the exact
|
||||
number of open days related to your leave.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_open_ask_holidays_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="act_window_id" ref="open_ask_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_ask_holidays_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="act_window_id" ref="open_ask_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_ask_holidays_calendar" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="view_id" ref="view_holiday_new_calendar"/>
|
||||
<field name="act_window_id" ref="open_ask_holidays"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_ask_holidays_new"
|
||||
parent="menu_hr_holidays_my_leaves"
|
||||
action="open_ask_holidays"
|
||||
sequence="22"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="request_approve_holidays">
|
||||
<field name="name">Requests to Approve</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{
|
||||
'default_type': 'remove',
|
||||
'search_default_approve':1,
|
||||
}</field>
|
||||
<field name="domain">[('type','=','remove')]</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_holidays_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="act_window_id" ref="request_approve_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_holidays_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="act_window_id" ref="request_approve_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="open_allocation_holidays" model="ir.actions.act_window">
|
||||
<field name="name">Allocation Request</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form</field>
|
||||
<field name="context">{
|
||||
'default_type':'add',
|
||||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave allocation request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('type','=','add'), ('user_id', '=', uid)]</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_allocation_holidays_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday_allocation_tree"/>
|
||||
<field name="act_window_id" ref="open_allocation_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_allocation_holidays_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="act_window_id" ref="open_allocation_holidays"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_allocation_holidays"
|
||||
parent="menu_hr_holidays_my_leaves"
|
||||
action="open_allocation_holidays"
|
||||
sequence="30"/>
|
||||
|
||||
<record id="request_approve_allocation" model="ir.actions.act_window">
|
||||
<field name="name">Allocation Request</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{
|
||||
'default_type': 'add',
|
||||
'search_default_approve':1,
|
||||
}</field>
|
||||
<field name="domain">[('type','=','add')]</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_allocation_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday_allocation_tree"/>
|
||||
<field name="act_window_id" ref="request_approve_allocation"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_allocation_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new"/>
|
||||
<field name="act_window_id" ref="request_approve_allocation"/>
|
||||
</record>
|
||||
|
||||
<record id="open_company_allocation" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Summary</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form</field>
|
||||
<field name="view_id" eval="view_holiday_simple"/>
|
||||
<field name="context">{
|
||||
'search_default_group_type': 1,
|
||||
'search_default_year': 1 ,
|
||||
}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('holiday_type','=','employee'), ('user_id', '=', uid)]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_company_allocation"
|
||||
parent="menu_hr_holidays_my_leaves"
|
||||
action="open_company_allocation"
|
||||
sequence="10"/>
|
||||
|
||||
<record id="open_employee_leaves" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Overview</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,calendar</field>
|
||||
<field name="view_id" eval="view_holiday"/>
|
||||
<field name="context">{'default_type': 'remove',}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('type','=','remove')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="open_department_holidays_approve" model="ir.actions.act_window">
|
||||
<field name="name">Department Leaves</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar</field>
|
||||
<field name="context">{'search_default_department':1, 'search_default_approve':1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('type','=','remove')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_department_leave_approve"
|
||||
name="Leaves to Approve"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"
|
||||
action="open_department_holidays_approve"
|
||||
sequence="1"/>
|
||||
|
||||
<record id="open_department_holidays_allocation_approve" model="ir.actions.act_window">
|
||||
<field name="name">Department Leaves Allocation</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar</field>
|
||||
<field name="context">{'default_type':'add', 'search_default_department':1, 'search_default_approve':1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave allocation.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('type','=','add')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_department_leave_allocation_approve" groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"
|
||||
name="Allocations to Approve"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
action="open_department_holidays_allocation_approve"
|
||||
sequence="2"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_employee_leave"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"
|
||||
action="open_employee_leaves"
|
||||
sequence="4"/>
|
||||
|
||||
<!-- Holidays status -->
|
||||
<record id="view_holidays_status_filter" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.filter</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Leave Type">
|
||||
<field name="name" string="Leave Types"/>
|
||||
<field name="categ_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="edit_holiday_status_form" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.form</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Leave Type">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" type="object" name="toggle_active" icon="fa-archive">
|
||||
<field name="active" widget="boolean_button"
|
||||
options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</div>
|
||||
<group>
|
||||
<group name="description" string="Description">
|
||||
<field name="name"/>
|
||||
<field name="double_validation"/>
|
||||
<field name="limit"/>
|
||||
</group>
|
||||
<group name="options" string="Options">
|
||||
<field name="categ_id"/>
|
||||
<field name="color_name"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_status_tree" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.tree</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leave Type">
|
||||
<field name="name"/>
|
||||
<field name="max_leaves"/>
|
||||
<field name="leaves_taken"/>
|
||||
<field name="remaining_leaves"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holiday_status_view_kanban" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.kanban</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="o_kanban_mobile">
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click">
|
||||
<div>
|
||||
<strong><field name="name"/></strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Max Leaves: <field name="max_leaves"/></span>
|
||||
<span class="pull-right">Leaves Taken: <field name="leaves_taken"/></span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_status_normal_tree" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.normal.tree</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="priority">35</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leave Type">
|
||||
<field name="name"/>
|
||||
<field name="limit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_holidays_status_search" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.search</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Leave Type">
|
||||
<field name="name" string="Leave Types"/>
|
||||
<field name="categ_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="open_view_holiday_status" model="ir.actions.act_window">
|
||||
<field name="name">Leave Types</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.holidays.status</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form</field>
|
||||
<field name="view_id" eval="view_holiday_status_normal_tree"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_status_search"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_configuration"
|
||||
name="Configuration"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="100"
|
||||
groups="hr_holidays.group_hr_holidays_manager"
|
||||
action="open_view_holiday_status"/>
|
||||
|
||||
<!-- Shortcuts -->
|
||||
<record id="act_hr_employee_holiday_request" model="ir.actions.act_window">
|
||||
<field name="name">Leaves</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="src_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_employee_id': [active_id], 'default_employee_id': active_id, 'search_default_group_type': 1,
|
||||
'search_default_year': 1}</field>
|
||||
<field name="domain">[('holiday_type','=','employee'), ('holiday_status_id.limit', '=', False), ('state','!=', 'refuse')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="act_hr_employee_holiday_request_approved" model="ir.actions.act_window">
|
||||
<field name="name">Leaves to be reported in Payslip</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="src_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_employee_id': [active_id], 'search_default_validated': True, 'search_default_gray': True}</field>
|
||||
<field name="domain">[('date_from','>=', context_today().strftime("%Y-%m-1")), ('date_from','<', ((context_today() + relativedelta(months=1)).strftime('%Y-%m-1')) )]</field>
|
||||
<field name="view_id" eval="view_holiday_allocation_tree_customize"/>
|
||||
</record>
|
||||
|
||||
<!-- Assing leave -->
|
||||
<record id="hr_holidays_leaves_assign_tree_view" model="ir.ui.view">
|
||||
<field name="name">hr.employee.leave.tree</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Assign Leaves" editable="bottom">
|
||||
<field name="name" string="Employee"/>
|
||||
<field name="remaining_leaves" string="Remaining Legal Leaves"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_leaves_assign_legal" model="ir.actions.act_window">
|
||||
<field name="name">Allocate Leaves for Employees</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="hr_holidays_leaves_assign_tree_view"/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
You can assign remaining Legal Leaves for each employee, Odoo
|
||||
will automatically create and validate allocation requests.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="hr_holidays_action_request_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Leave Request to Approve</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{
|
||||
'default_type': 'remove',
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id,
|
||||
'search_default_approve':1}
|
||||
</field>
|
||||
<field name="domain">[('type','=','remove')]</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_action_allocation_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Allocation Requests to Approve</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{
|
||||
'default_type': 'add',
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id,
|
||||
'search_default_approve':1}
|
||||
</field>
|
||||
<field name="domain">[('type','=','add')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_employee_action_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Absent Employees</field>
|
||||
<field name="res_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{
|
||||
'search_default_is_absent_totay': 1,
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id}
|
||||
</field>
|
||||
<field name="search_view_id" ref="hr.view_employee_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_holidays_leaves_analysis" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Analysis</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,pivot</field>
|
||||
<field name="domain">[('holiday_type','=','employee')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_holidays_leaves_analysis_filtered" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Analysis</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,pivot</field>
|
||||
<field name="domain">[('holiday_type','=','employee')]</field>
|
||||
<field name="context">{
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id}
|
||||
</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,215 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_hr_leave_allocation_filter" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.filter_allocations</field>
|
||||
<field name="model">hr.leave.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search allocations">
|
||||
<field name="name"/>
|
||||
<filter domain="[('state','in',('confirm', 'validate1'))]" string="To Approve" name="approve"/>
|
||||
<filter string="Approved Allocations" domain="[('state', '=', 'validate')]" name="validated"/>
|
||||
<separator/>
|
||||
<filter name="active_types" string="Active Types" domain="[('holiday_status_id.active', '=', True)]" help="Filters only on allocations that belong to an leave type that is 'active' (active field is True)"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<separator/>
|
||||
<filter string="My Department Leaves" name="department" domain="[('department_id.manager_id.user_id', '=', uid)]" help="My Department Leaves"/>
|
||||
<filter name="my_team_leaves" string="My Team Leaves" domain="[('employee_id.parent_id.user_id', '=', uid)]" groups="hr_holidays.group_hr_holidays_manager" help="Leaves of Your Team Member"/>
|
||||
<separator/>
|
||||
<filter name="year" string="Current Year"
|
||||
domain="[('holiday_status_id.active', '=', True)]" help="Active Allocations"/>
|
||||
<separator/>
|
||||
<filter string="My Allocations" name="my_leaves" domain="[('employee_id.user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_name" string="Description" context="{'group_by':'name'}"/>
|
||||
<filter name="group_employee" string="Employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter name="group_category" string="Category" context="{'group_by':'category_id'}"/>
|
||||
<filter name="group_second_approver_id" string="Validator" context="{'group_by':'second_approver_id'}"/>
|
||||
<filter name="group_type" string="Type" context="{'group_by':'holiday_status_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="edit_new_allocation" model="ir.ui.view">
|
||||
<field name="name">Allocation Request</field>
|
||||
<field name="model">hr.leave.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Allocation Request">
|
||||
<field name="can_reset" invisible="1"/>
|
||||
<header>
|
||||
<button string="Confirm" name="action_confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button string="Approve" name="action_approve" states="confirm" type="object" groups="hr_holidays.group_hr_holidays_user" class="oe_highlight"/>
|
||||
<button string="Validate" name="action_validate" states="validate1" type="object" groups="hr_holidays.group_hr_holidays_manager" class="oe_highlight"/>
|
||||
<button string="Refuse" name="action_refuse" states="confirm,validate,validate1" type="object" groups="hr_holidays.group_hr_holidays_user"/>
|
||||
<button string="Reset to Draft" name="action_draft" type="object"
|
||||
attrs="{'invisible': ['|', ('can_reset', '=', False), ('state', 'not in', ['confirm', 'refuse'])]}"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,validate"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="display_name"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" attrs="{'readonly':[('state','!=','draft'),('state','!=','confirm')]}"/>
|
||||
<field name="holiday_status_id" context="{'employee_id':employee_id}"/>
|
||||
<label for="number_of_days_temp" string="Duration"/>
|
||||
<div>
|
||||
<div>
|
||||
<field name="number_of_days_temp" class="oe_inline"/> days
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="holiday_type" string="Mode" groups="hr_holidays.group_hr_holidays_user" context="{'employee_id':employee_id}" />
|
||||
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')],'invisible':[('holiday_type','!=','employee')]}" groups="hr_holidays.group_hr_holidays_user"/>
|
||||
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'invisible':[('holiday_type','!=','category')]}"/>
|
||||
<field name="department_id" groups="hr_holidays.group_hr_holidays_user" attrs="{'invisible':[('holiday_type','=','category')]}"/>
|
||||
</group>
|
||||
<field name="notes" nolabel="1" colspan="4" placeholder="Add a reason..."/>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_allocation_tree" model="ir.ui.view">
|
||||
<field name="name">hr.leave.allocation.tree</field>
|
||||
<field name="model">hr.leave.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == 'draft'" string="Allocation Requests"
|
||||
decoration-bf="message_needaction == True">
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id" invisible="1"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_view_list_my_allocation" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.my.allocation.tree</field>
|
||||
<field name="model">hr.leave.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == 'draft'" string="Allocation Requests"
|
||||
decoration-bf="message_needaction == True">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name"/>
|
||||
<field name="number_of_days" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_allocation_tree_customize" model="ir.ui.view">
|
||||
<field name="name">hr.leave.allocation.tree.customize</field>
|
||||
<field name="model">hr.leave.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Allocation Requests" editable="top">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_type"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="number_of_days_temp" string="Allocated Days" sum="Remaining Days"/>
|
||||
<field name="state"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="open_allocation" model="ir.actions.act_window">
|
||||
<field name="name">Allocation Request</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave allocation request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="domain">[('employee_id.user_id', '=', uid)]</field>
|
||||
<field name="view_id" ref="edit_new_allocation"/>
|
||||
<field name="search_view_id" ref="view_hr_leave_allocation_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="request_approve_allocation" model="ir.actions.act_window">
|
||||
<field name="name">Allocation Request</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{
|
||||
'search_default_approve':1,
|
||||
}</field>
|
||||
<field name="view_id" ref="edit_new_allocation"/>
|
||||
<field name="search_view_id" ref="view_hr_leave_allocation_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="open_department_holidays_allocation_approve" model="ir.actions.act_window">
|
||||
<field name="name">Department Leaves Allocation</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_department':1, 'search_default_approve':1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave allocation.
|
||||
</p>
|
||||
</field>
|
||||
<field name="search_view_id" ref="view_hr_leave_allocation_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_action_allocation_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Allocation Requests to Approve</field>
|
||||
<field name="res_model">hr.leave.allocation</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id,
|
||||
'search_default_approve':1}
|
||||
</field>
|
||||
<field name="search_view_id" ref="view_hr_leave_allocation_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_allocation_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_allocation_tree"/>
|
||||
<field name="act_window_id" ref="open_allocation"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_allocation_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_new_allocation"/>
|
||||
<field name="act_window_id" ref="open_allocation"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_allocation_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_allocation_tree"/>
|
||||
<field name="act_window_id" ref="request_approve_allocation"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_allocation_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_new_allocation"/>
|
||||
<field name="act_window_id" ref="request_approve_allocation"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,113 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<odoo>
|
||||
|
||||
<!-- Holidays status -->
|
||||
<record id="view_holidays_status_filter" model="ir.ui.view">
|
||||
<field name="name">hr.leave.type.filter</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Leave Type">
|
||||
<field name="name" string="Leave Types"/>
|
||||
<field name="categ_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="edit_holiday_status_form" model="ir.ui.view">
|
||||
<field name="name">hr.leave.type.form</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Leave Type">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button class="oe_stat_button" type="object" name="toggle_active" icon="fa-archive">
|
||||
<field name="active" widget="boolean_button"
|
||||
options='{"terminology": "archive"}'/>
|
||||
</button>
|
||||
</div>
|
||||
<group>
|
||||
<group name="description" string="Description">
|
||||
<field name="name"/>
|
||||
<field name="double_validation"/>
|
||||
<field name="limit"/>
|
||||
</group>
|
||||
<group name="options" string="Options">
|
||||
<field name="categ_id"/>
|
||||
<field name="color_name"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_status_tree" model="ir.ui.view">
|
||||
<field name="name">hr.leave.type.tree</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leave Type">
|
||||
<field name="name"/>
|
||||
<field name="max_leaves"/>
|
||||
<field name="leaves_taken"/>
|
||||
<field name="remaining_leaves"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holiday_status_view_kanban" model="ir.ui.view">
|
||||
<field name="name">hr.leave.type.kanban</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban class="o_kanban_mobile">
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="oe_kanban_global_click">
|
||||
<div>
|
||||
<strong><field name="name"/></strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Max Leaves: <field name="max_leaves"/></span>
|
||||
<span class="pull-right">Leaves Taken: <field name="leaves_taken"/></span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_status_normal_tree" model="ir.ui.view">
|
||||
<field name="name">hr.leave.type.normal.tree</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="priority">35</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Leave Type">
|
||||
<field name="name"/>
|
||||
<field name="limit"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_holidays_status_search" model="ir.ui.view">
|
||||
<field name="name">hr.leave.type.search</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Leave Type">
|
||||
<field name="name" string="Leave Types"/>
|
||||
<field name="categ_id"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="open_view_holiday_status" model="ir.actions.act_window">
|
||||
<field name="name">Leave Types</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.leave.type</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form</field>
|
||||
<field name="view_id" eval="view_holiday_status_normal_tree"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_status_search"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,437 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<odoo>
|
||||
|
||||
<!-- Graph report -->
|
||||
<record id="view_evaluation_report_graph" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.graph</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Appraisal Analysis" stacked="True">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="holiday_status_id" type="row"/>
|
||||
<field name="date_from" type="col"/>
|
||||
<field name="number_of_days" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_hr_holidays_filter" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.filter</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Leave">
|
||||
<field name="name"/>
|
||||
<filter domain="[('state','in',('confirm','validate1'))]" string="To Approve" name="approve"/>
|
||||
<filter string="Approved Leaves" domain="[('state', '=', 'validate')]" name="validated"/>
|
||||
<separator/>
|
||||
<filter name="active_types" string="Active Types" domain="[('holiday_status_id.active', '=', True)]" help="Filters only on requests that belong to an leave type that is 'active' (active field is True)"/>
|
||||
<separator/>
|
||||
<filter string="Unread Messages" name="message_needaction" domain="[('message_needaction','=',True)]"/>
|
||||
<separator/>
|
||||
<filter string="My Department Leaves" name="department" domain="[('department_id.manager_id.user_id', '=', uid)]" help="My Department Leaves"/>
|
||||
<filter name="my_team_leaves" string="My Team Leaves" domain="[('employee_id.parent_id.user_id', '=', uid)]" groups="hr_holidays.group_hr_holidays_manager" help="Leaves of Your Team Member"/>
|
||||
<separator/>
|
||||
<filter string="To Report in Payslip" name="gray" domain="[('payslip_status', '=', False)]" groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
<separator/>
|
||||
<filter string="To Do" name="todo" domain="[('payslip_status', '=', False), ('holiday_status_id.active', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="year" string="Current Year"
|
||||
domain="[('holiday_status_id.active', '=', True)]" help="Active Leaves"/>
|
||||
<separator/>
|
||||
<filter string="My Leaves" name="my_leaves" domain="[('employee_id.user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<field name="employee_id"/>
|
||||
<field name="department_id"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_name" string="Description" context="{'group_by':'name'}"/>
|
||||
<filter name="group_employee" string="Employee" context="{'group_by':'employee_id'}"/>
|
||||
<filter name="group_category" string="Category" context="{'group_by':'category_id'}"/>
|
||||
<filter name="group_manager" string="Manager" context="{'group_by':'manager_id'}"/>
|
||||
<filter name="group_second_approver_id" string="Validator" context="{'group_by':'second_approver_id'}"/>
|
||||
<filter name="group_type" string="Type" context="{'group_by':'holiday_status_id'}"/>
|
||||
<separator/>
|
||||
<filter name="group_date_from" string="Start Month" context="{'group_by':'date_from'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Holidays: Leave Request -->
|
||||
|
||||
<record id="view_holiday_new_calendar" model="ir.ui.view">
|
||||
<field name="name">Leave Request</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<calendar string="Leave Request" date_start="date_from" date_stop="date_to" mode="month" quick_add="False" color="employee_id">
|
||||
<field name="display_name"/>
|
||||
</calendar>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="edit_holiday_new_request" model="ir.ui.view">
|
||||
<field name="name">Leave Request</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Leave Request">
|
||||
<field name="can_reset" invisible="1"/>
|
||||
<header>
|
||||
<button string="Confirm" name="action_confirm" states="draft" type="object" class="oe_highlight"/>
|
||||
<button string="Approve" name="action_approve" states="confirm" type="object" groups="hr_holidays.group_hr_holidays_user" class="oe_highlight"/>
|
||||
<button string="Validate" name="action_validate" states="validate1" type="object" groups="hr_holidays.group_hr_holidays_manager" class="oe_highlight"/>
|
||||
<button string="Refuse" name="action_refuse" states="confirm,validate,validate1" type="object" groups="hr_holidays.group_hr_holidays_user"/>
|
||||
<button string="Reset to Draft" name="action_draft" type="object"
|
||||
attrs="{'invisible': ['|', ('can_reset', '=', False), ('state', 'not in', ['confirm', 'refuse'])]}"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,validate"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<h1><field name="display_name"/></h1>
|
||||
</div>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" attrs="{'readonly':[('state','!=','draft'),('state','!=','confirm')]}"/>
|
||||
<field name="holiday_status_id" context="{'employee_id':employee_id}"/>
|
||||
<label for="number_of_days_temp" string="Duration"/>
|
||||
<div>
|
||||
<div>
|
||||
<field name="date_from" class="oe_inline"/>
|
||||
<label string="-" class="oe_inline"/>
|
||||
<field name="date_to" class="oe_inline"/>
|
||||
</div>
|
||||
<div>
|
||||
<field name="number_of_days_temp" class="oe_inline"/> days
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="holiday_type" attrs="{'readonly':[('state','!=','draft')]}" string="Mode" groups="hr_holidays.group_hr_holidays_user" context="{'employee_id':employee_id}" />
|
||||
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')],'invisible':[('holiday_type','!=','employee')]}" groups="hr_holidays.group_hr_holidays_user"/>
|
||||
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'readonly': [('state','!=','draft'), ('state','!=','confirm')], 'invisible':[('holiday_type','!=','category')]}"/>
|
||||
<field name="department_id" groups="hr_holidays.group_hr_holidays_user" attrs="{'readonly':['|',('state','=', 'validate'),('holiday_type','!=','department')],'invisible':[('holiday_type','=','category')]}"/>
|
||||
<field name="payslip_status" groups="hr_holidays.group_hr_holidays_manager" widget="toggle_button"/>
|
||||
</group>
|
||||
<div groups="hr_holidays.group_hr_holidays_manager">
|
||||
<separator string="Comment by Manager"/>
|
||||
<field name="report_note" placeholder="e.g. Report to the next month..."/>
|
||||
</div>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.tree</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree decoration-danger="state == 'refuse'" decoration-info="state == ' draft'" string="Leave Requests"
|
||||
decoration-bf="message_needaction == True">
|
||||
<field name="employee_id"/>
|
||||
<field name="holiday_type" string="Mode" groups="base.group_no_one"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="name"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
<field name="number_of_days" string="Number of Days" sum="Remaining Days"/>
|
||||
<field name="state"/>
|
||||
<field name="payslip_status" widget="toggle_button" options='{"active": "Reported in last payslips", "inactive": "To Report in Payslip"}' groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
<field name="category_id" invisible="1"/>
|
||||
<field name="department_id" invisible="not context.get('set_visible',False)"/>
|
||||
<field name="manager_id" invisible="1"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_holidays_dashboard" model="ir.actions.act_window">
|
||||
<field name="name">All Leaves</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="context">{'search_default_year': 1, 'search_default_group_employee': 1}</field>
|
||||
<field name="domain">[('holiday_type','=','employee'), ('state', '!=', 'refuse')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Leaves"
|
||||
id="menu_hr_holidays_root"
|
||||
sequence="95"
|
||||
web_icon="hr_holidays,static/description/icon.png"
|
||||
groups="base.group_user"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_dashboard"
|
||||
name="Dashboard"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="1"
|
||||
action="action_hr_holidays_dashboard"
|
||||
groups="hr_holidays.group_hr_holidays_manager"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_my_leaves"
|
||||
name="My Leaves"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="2"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_approvals"
|
||||
name="Managers"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="3"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_report"
|
||||
name="Reporting"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="99"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"/>
|
||||
|
||||
<record id="open_ask_holidays" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Request</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new_request"/>
|
||||
<field name="domain">[('user_id', '=', uid)]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new leave request.
|
||||
</p><p>
|
||||
Once you have recorded your leave request, it will be sent
|
||||
to a manager for validation. Be sure to set the right leave
|
||||
type (recuperation, legal leaves, sickness) and the exact
|
||||
number of open days related to your leave.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_open_ask_holidays_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="act_window_id" ref="open_ask_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_ask_holidays_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="3"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_holiday_new_request"/>
|
||||
<field name="act_window_id" ref="open_ask_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_open_ask_holidays_calendar" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">calendar</field>
|
||||
<field name="view_id" ref="view_holiday_new_calendar"/>
|
||||
<field name="act_window_id" ref="open_ask_holidays"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_ask_holidays_new"
|
||||
parent="menu_hr_holidays_my_leaves"
|
||||
action="open_ask_holidays"
|
||||
sequence="22"/>
|
||||
|
||||
<record model="ir.actions.act_window" id="request_approve_holidays">
|
||||
<field name="name">Requests to Approve</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{
|
||||
'search_default_approve':1,
|
||||
}</field>
|
||||
<field name="view_id" ref="edit_new_allocation"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_holidays_tree" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="act_window_id" ref="request_approve_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="action_request_approve_holidays_form" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="edit_new_allocation"/>
|
||||
<field name="act_window_id" ref="request_approve_holidays"/>
|
||||
</record>
|
||||
|
||||
<record id="open_employee_leaves" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Overview</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,kanban,form,calendar</field>
|
||||
<field name="view_id" eval="view_holiday"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="open_department_holidays_approve" model="ir.actions.act_window">
|
||||
<field name="name">Department Leaves</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar</field>
|
||||
<field name="context">{'search_default_department':1, 'search_default_approve':1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click here to create a new leave request.
|
||||
</p>
|
||||
</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_department_leave_approve"
|
||||
name="Leaves to Approve"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"
|
||||
action="open_department_holidays_approve"
|
||||
sequence="1"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_department_leave_allocation_approve" groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"
|
||||
name="Allocations to Approve"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
action="open_department_holidays_allocation_approve"
|
||||
sequence="2"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_employee_leave"
|
||||
parent="menu_hr_holidays_approvals"
|
||||
groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"
|
||||
action="open_employee_leaves"
|
||||
sequence="4"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_holidays_configuration"
|
||||
name="Configuration"
|
||||
parent="menu_hr_holidays_root"
|
||||
sequence="100"
|
||||
groups="hr_holidays.group_hr_holidays_manager"
|
||||
action="open_view_holiday_status"/>
|
||||
|
||||
<!-- Shortcuts -->
|
||||
<record id="act_hr_employee_holiday_request_approved" model="ir.actions.act_window">
|
||||
<field name="name">Leaves to be reported in Payslip</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="src_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_employee_id': [active_id], 'search_default_validated': True, 'search_default_gray': True}</field>
|
||||
<field name="domain">[('date_from','>=', context_today().strftime("%Y-%m-1")), ('date_from','<', ((context_today() + relativedelta(months=1)).strftime('%Y-%m-1')) )]</field>
|
||||
<field name="view_id" eval="view_allocation_tree_customize"/>
|
||||
</record>
|
||||
|
||||
<!-- Assing leave -->
|
||||
<record id="hr_holidays_action_request_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Leave Request to Approve</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id,
|
||||
'search_default_approve':1}
|
||||
</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_holidays_leaves_analysis" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Analysis</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,pivot</field>
|
||||
<field name="domain">[('holiday_type','=','employee')]</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_holidays_leaves_analysis_filtered" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Analysis</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,pivot</field>
|
||||
<field name="domain">[('holiday_type','=','employee')]</field>
|
||||
<field name="context">{
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id}
|
||||
</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_pivot" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.report_pivot</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Leaves Summary">
|
||||
<field name="employee_id" type="row"/>
|
||||
<field name="date_from" type="col"/>
|
||||
<field name="number_of_days" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_graph" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.report_graph</field>
|
||||
<field name="model">hr.leave</field>
|
||||
<field name="priority">20</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Leaves Summary">
|
||||
<field name="employee_id"/>
|
||||
<field name="number_of_days" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_hr_available_holidays_report" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Analysis</field>
|
||||
<field name="res_model">hr.leave</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">graph,pivot,calendar,form</field>
|
||||
<field name="view_id"></field> <!-- force empty -->
|
||||
<field name="context">{'search_default_leaves':1}</field>
|
||||
<field name="search_view_id" ref="view_hr_holidays_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="action_window_leave_pivot" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">pivot</field>
|
||||
<field name="view_id" ref="view_holiday_pivot"/>
|
||||
<field name="act_window_id" ref="action_hr_available_holidays_report"/>
|
||||
</record>
|
||||
|
||||
<record id="action_window_leave_graph" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">graph</field>
|
||||
<field name="view_id" ref="view_holiday_graph"/>
|
||||
<field name="act_window_id" ref="action_hr_available_holidays_report"/>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
name="Leaves Analysis"
|
||||
id="menu_hr_available_holidays_report_tree"
|
||||
action="action_hr_available_holidays_report"
|
||||
parent="menu_hr_holidays_report" sequence="5"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_open_allocation"
|
||||
parent="menu_hr_holidays_my_leaves"
|
||||
action="open_allocation"
|
||||
sequence="30"/>
|
||||
|
||||
</odoo>
|
||||
@@ -1,5 +1,59 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<odoo>
|
||||
|
||||
<record id="act_hr_employee_holiday_request" model="ir.actions.act_window">
|
||||
<field name="name">Leaves</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.leave.report</field>
|
||||
<field name="src_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'search_default_employee_id': [active_id], 'default_employee_id': active_id, 'search_default_group_type': 1,
|
||||
'search_default_year': 1}</field>
|
||||
<field name="domain">[('holiday_type','=','employee'), ('holiday_status_id.limit', '=', False), ('state','!=', 'refuse')]</field>
|
||||
<field name="search_view_id" ref="view_hr_leave_allocation_filter"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_leaves_assign_tree_view" model="ir.ui.view">
|
||||
<field name="name">hr.employee.leave.tree</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Assign Leaves" editable="bottom">
|
||||
<field name="name" string="Employee"/>
|
||||
<field name="remaining_leaves" string="Remaining Legal Leaves"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_leaves_assign_legal" model="ir.actions.act_window">
|
||||
<field name="name">Allocate Leaves for Employees</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="hr_holidays_leaves_assign_tree_view"/>
|
||||
<field name="help" type="html">
|
||||
<p>
|
||||
You can assign remaining Legal Leaves for each employee, Odoo
|
||||
will automatically create and validate allocation requests.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_employee_action_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Absent Employees</field>
|
||||
<field name="res_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
<field name="context">{
|
||||
'search_default_is_absent_totay': 1,
|
||||
'search_default_department_id': [active_id],
|
||||
'default_department_id': active_id}
|
||||
</field>
|
||||
<field name="search_view_id" ref="hr.view_employee_filter"/>
|
||||
</record>
|
||||
|
||||
<!--Hr Department Inherit Kanban view-->
|
||||
<record id="hr_department_view_kanban" model="ir.ui.view">
|
||||
<field name="name">hr.department.kanban.inherit</field>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<!-- Holidays Category -->
|
||||
|
||||
<record model="hr.holidays.status" id="holiday_status_heures_sup">
|
||||
<record model="hr.leave.type" id="holiday_status_heures_sup">
|
||||
<field name="name">Heures Supplementaires</field>
|
||||
<field name="limit">True</field>
|
||||
<field name="color_name">lightblue</field>
|
||||
|
||||
@@ -12,9 +12,9 @@ def post_init(cr, registry):
|
||||
from odoo import api, SUPERUSER_ID
|
||||
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
for leave_type in env['hr.holidays.status'].search([('timesheet_generate', '=', True), ('timesheet_project_id', '=', False)]):
|
||||
company = leave_type.company_id or env.user.company_id
|
||||
leave_type.write({
|
||||
for hr_leave_type in env['hr.leave.type'].search([('timesheet_generate', '=', True), ('timesheet_project_id', '=', False)]):
|
||||
company = hr_leave_type.company_id or env.user.company_id
|
||||
hr_leave_type.write({
|
||||
'timesheet_project_id': company.leave_timesheet_project_id.id,
|
||||
'timesheet_task_id': company.leave_timesheet_task_id.id,
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ from odoo.exceptions import UserError
|
||||
class AccountAnalyticLine(models.Model):
|
||||
_inherit = 'account.analytic.line'
|
||||
|
||||
holiday_id = fields.Many2one("hr.holidays", string='Leave Request')
|
||||
holiday_id = fields.Many2one("hr.leave", string='Leave Request')
|
||||
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
|
||||
@@ -6,7 +6,7 @@ from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class HolidaysType(models.Model):
|
||||
_inherit = "hr.holidays.status"
|
||||
_inherit = "hr.leave.type"
|
||||
|
||||
def _default_project_id(self):
|
||||
company = self.company_id if self.company_id else self.env.user.company_id
|
||||
@@ -39,7 +39,7 @@ class HolidaysType(models.Model):
|
||||
|
||||
|
||||
class Holidays(models.Model):
|
||||
_inherit = "hr.holidays"
|
||||
_inherit = "hr.leave"
|
||||
|
||||
timesheet_ids = fields.One2many('account.analytic.line', 'holiday_id', string="Analytic Lines")
|
||||
|
||||
@@ -50,8 +50,7 @@ class Holidays(models.Model):
|
||||
"""
|
||||
# create the timesheet on the vacation project
|
||||
for holiday in self.filtered(
|
||||
lambda request: request.type == 'remove' and
|
||||
request.holiday_type == 'employee' and
|
||||
lambda request: request.holiday_type == 'employee' and
|
||||
request.holiday_status_id.timesheet_project_id and
|
||||
request.holiday_status_id.timesheet_task_id):
|
||||
holiday_project = holiday.holiday_status_id.timesheet_project_id
|
||||
|
||||
@@ -14,7 +14,7 @@ class TestTimesheetHolidaysCreate(common.TransactionCase):
|
||||
|
||||
def test_status_create(self):
|
||||
"""Ensure that when a status is created, it fullfills the project and task constrains"""
|
||||
status = self.env['hr.holidays.status'].create({
|
||||
status = self.env['hr.leave.type'].create({
|
||||
'name': 'A nice Leave Type',
|
||||
'limit': True
|
||||
})
|
||||
@@ -39,14 +39,14 @@ class TestTimesheetHolidays(TestTimesheet):
|
||||
self.internal_project = self.env.user.company_id.leave_timesheet_project_id
|
||||
self.internal_task_leaves = self.env.user.company_id.leave_timesheet_task_id
|
||||
|
||||
self.leave_type_with_ts = self.env['hr.holidays.status'].create({
|
||||
self.hr_leave_type_with_ts = self.env['hr.leave.type'].create({
|
||||
'name': 'Leave Type with timesheet generation',
|
||||
'limit': True,
|
||||
'timesheet_generate': True,
|
||||
'timesheet_project_id': self.internal_project.id,
|
||||
'timesheet_task_id': self.internal_task_leaves.id,
|
||||
})
|
||||
self.leave_type_no_ts = self.env['hr.holidays.status'].create({
|
||||
self.hr_leave_type_no_ts = self.env['hr.leave.type'].create({
|
||||
'name': 'Leave Type without timesheet generation',
|
||||
'limit': True,
|
||||
'timesheet_generate': False,
|
||||
@@ -55,31 +55,30 @@ class TestTimesheetHolidays(TestTimesheet):
|
||||
})
|
||||
|
||||
# HR Officer allocates some leaves to the employee 1
|
||||
self.Holidays = self.env['hr.holidays'].with_context(mail_create_nolog=True, mail_notrack=True)
|
||||
self.leave_allocation_with_ts = self.Holidays.sudo().create({
|
||||
self.Requests = self.env['hr.leave'].with_context(mail_create_nolog=True, mail_notrack=True)
|
||||
self.Allocations = self.env['hr.leave.allocation'].with_context(mail_create_nolog=True, mail_notrack=True)
|
||||
self.hr_leave_allocation_with_ts = self.Allocations.sudo().create({
|
||||
'name': 'Days for limited category with timesheet',
|
||||
'employee_id': self.empl_employee.id,
|
||||
'holiday_status_id': self.leave_type_with_ts.id,
|
||||
'type': 'add',
|
||||
'holiday_status_id': self.hr_leave_type_with_ts.id,
|
||||
'number_of_days_temp': 10,
|
||||
})
|
||||
self.leave_allocation_with_ts.action_approve()
|
||||
self.leave_allocation_no_ts = self.Holidays.sudo().create({
|
||||
self.hr_leave_allocation_with_ts.action_approve()
|
||||
self.hr_leave_allocation_no_ts = self.Allocations.sudo().create({
|
||||
'name': 'Days for limited category without timesheet',
|
||||
'employee_id': self.empl_employee.id,
|
||||
'holiday_status_id': self.leave_type_no_ts.id,
|
||||
'type': 'add',
|
||||
'holiday_status_id': self.hr_leave_type_no_ts.id,
|
||||
'number_of_days_temp': 10,
|
||||
})
|
||||
self.leave_allocation_no_ts.action_approve()
|
||||
self.hr_leave_allocation_no_ts.action_approve()
|
||||
|
||||
def test_validate_with_timesheet(self):
|
||||
# employee creates a leave request
|
||||
number_of_days = (self.leave_end_datetime - self.leave_start_datetime).days+1
|
||||
holiday = self.Holidays.sudo(self.user_employee.id).create({
|
||||
holiday = self.Requests.sudo(self.user_employee.id).create({
|
||||
'name': 'Leave 1',
|
||||
'employee_id': self.empl_employee.id,
|
||||
'holiday_status_id': self.leave_type_with_ts.id,
|
||||
'holiday_status_id': self.hr_leave_type_with_ts.id,
|
||||
'date_from': self.leave_start_datetime,
|
||||
'date_to': self.leave_end_datetime,
|
||||
'number_of_days_temp': number_of_days,
|
||||
@@ -94,10 +93,10 @@ class TestTimesheetHolidays(TestTimesheet):
|
||||
def test_validate_without_timesheet(self):
|
||||
# employee creates a leave request
|
||||
number_of_days = (self.leave_end_datetime - self.leave_start_datetime).days
|
||||
holiday = self.Holidays.sudo(self.user_employee.id).create({
|
||||
holiday = self.Requests.sudo(self.user_employee.id).create({
|
||||
'name': 'Leave 1',
|
||||
'employee_id': self.empl_employee.id,
|
||||
'holiday_status_id': self.leave_type_no_ts.id,
|
||||
'holiday_status_id': self.hr_leave_type_no_ts.id,
|
||||
'date_from': self.leave_start_datetime,
|
||||
'date_to': self.leave_end_datetime,
|
||||
'number_of_days_temp': number_of_days,
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
<odoo>
|
||||
|
||||
<record id="hr_holiday_status_view_form_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.status.form</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="name">hr.leave.type.form</field>
|
||||
<field name="model">hr.leave.type</field>
|
||||
<field name="inherit_id" ref="hr_holidays.edit_holiday_status_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='description']" position="after">
|
||||
|
||||
Reference in New Issue
Block a user