diff options
| author | RomainLibert <rli@odoo.com> | 2017-12-28 11:30:57 +0100 |
|---|---|---|
| committer | RomainLibert <rli@odoo.com> | 2018-01-15 10:38:31 +0100 |
| commit | f61687a4cdb0e22df19568c9b4ac3dbb579ca062 (patch) | |
| tree | 996357a067e14cb7e56e068b84195498adf07508 /addons | |
| parent | 1103dda8ae660d70c6fa0ac70e0f62f3b2bdf1dd (diff) | |
[IMP] hr_holidays : split hr.holidays into hr.leave and hr.leave.allocation
Purpose
=======
Have a clear distinction between leave and allocation requests instead of
using the same model to mix 2 different concepts.
Splitting the model will allow different business code to be run on each
model as allocations and leaves are not exactly the same thing; this
will add some code but simplify future improvements
Specification
=============
1/ Completely separate the models
Model hr.holidays has been split into leave.request and
leave.allocation.
2/ Make reporting working again by using an SQL view aggregating data
from leaves and allocations
A new report has been added in order to aggregate
datas from both allocations and requests. The views have been modified
accordingly.
Diffstat (limited to 'addons')
22 files changed, 932 insertions, 334 deletions
diff --git a/addons/hr_holidays/__manifest__.py b/addons/hr_holidays/__manifest__.py index 79a0e47b5e4..7361860c627 100644 --- a/addons/hr_holidays/__manifest__.py +++ b/addons/hr_holidays/__manifest__.py @@ -41,7 +41,6 @@ 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', ], 'demo': [ diff --git a/addons/hr_holidays/controllers/main.py b/addons/hr_holidays/controllers/main.py index 3b0b5ee1b0d..3c991502681 100644 --- a/addons/hr_holidays/controllers/main.py +++ b/addons/hr_holidays/controllers/main.py @@ -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() diff --git a/addons/hr_holidays/data/hr_holidays_data.xml b/addons/hr_holidays/data/hr_holidays_data.xml index 285afe48442..c6c155a385f 100644 --- a/addons/hr_holidays/data/hr_holidays_data.xml +++ b/addons/hr_holidays/data/hr_holidays_data.xml @@ -3,28 +3,28 @@ <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> @@ -33,26 +33,26 @@ <!-- Holidays-related subtypes for messaging / Chatter --> <record id="mt_holidays_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"> <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"> <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"> <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> diff --git a/addons/hr_holidays/data/hr_holidays_demo.xml b/addons/hr_holidays/data/hr_holidays_demo.xml index fbfc9602c50..fb9b43eead5 100644 --- a/addons/hr_holidays/data/hr_holidays_demo.xml +++ b/addons/hr_holidays/data/hr_holidays_demo.xml @@ -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> diff --git a/addons/hr_holidays/models/hr.py b/addons/hr_holidays/models/hr.py index a0e95494857..3f70bec2961 100644 --- a/addons/hr_holidays/models/hr.py +++ b/addons/hr_holidays/models/hr.py @@ -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)] diff --git a/addons/hr_holidays/models/hr_holidays.py b/addons/hr_holidays/models/hr_holidays.py index fc72a6a9caf..a21be760c68 100644 --- a/addons/hr_holidays/models/hr_holidays.py +++ b/addons/hr_holidays/models/hr_holidays.py @@ -19,7 +19,7 @@ HOURS_PER_DAY = 8 class HolidaysType(models.Model): - _name = "hr.holidays.status" + _name = "hr.leave.type" _description = "Leave Type" name = fields.Char('Leave Type', required=True, translate=True) @@ -68,27 +68,35 @@ class HolidaysType(models.Model): # 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([ + requests = self.env['hr.leave'].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 + 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 @@ -146,10 +154,10 @@ class HolidaysType(models.Model): 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 +180,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 +196,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') @@ -215,13 +217,10 @@ class Holidays(models.Model): can_reset = fields.Boolean('Can reset', compute='_compute_can_reset') @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): @@ -242,7 +241,6 @@ class Holidays(models.Model): ('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) @@ -252,7 +250,7 @@ class Holidays(models.Model): @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: + 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 \ @@ -263,7 +261,7 @@ class Holidays(models.Model): _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_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."), ] @@ -336,20 +334,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 +350,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 +367,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): @@ -434,6 +420,7 @@ class Holidays(models.Model): raise UserError(_('Leave request must be in Draft state ("To Submit") in order to confirm it.')) return self.write({'state': 'confirm'}) + # TODO: Do we have to remove this method? @api.multi def _check_security_action_approve(self): if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'): @@ -458,7 +445,6 @@ class Holidays(models.Model): 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, @@ -491,10 +477,10 @@ class Holidays(models.Model): 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': + if holiday.holiday_type == 'employee': holiday._validate_leave_request() elif holiday.holiday_type in ['category', 'department']: - leaves = self.env['hr.holidays'] + 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) @@ -506,9 +492,9 @@ class Holidays(models.Model): 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}) @@ -576,21 +562,329 @@ class Holidays(models.Model): return 'hr_holidays.mt_holidays_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 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(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_request/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_request/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(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 + return result + + +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') + + @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 + + _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.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 + + 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) + 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 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(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) + 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(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 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, + '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 _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 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): + self._check_security_action_refuse() + + 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 + + @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 + #################################################### + + @api.multi + def _track_subtype(self, init_values): + if 'state' in init_values and self.state == 'validate': + return 'hr_holidays.mt_holidays_approved' + elif 'state' in init_values and self.state == 'validate1': + return 'hr_holidays.mt_holidays_first_validated' + elif 'state' in init_values and self.state == 'confirm': + return 'hr_holidays.mt_holidays_confirmed' + elif 'state' in init_values and self.state == 'refuse': + return 'hr_holidays.mt_holidays_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(Holidays, self)._notification_recipients(message, groups) + 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='/hr_holidays/validate') + app_action = self._notification_link_helper('controller', controller='/hr_holidays_allocation/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='/hr_holidays_allocation/refuse') hr_actions += [{'url': ref_action, 'title': _('Refuse')}] new_group = ( @@ -602,9 +896,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(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 diff --git a/addons/hr_holidays/models/resource.py b/addons/hr_holidays/models/resource.py index 54e27c74cca..7a761e5650d 100644 --- a/addons/hr_holidays/models/resource.py +++ b/addons/hr_holidays/models/resource.py @@ -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') diff --git a/addons/hr_holidays/report/__init__.py b/addons/hr_holidays/report/__init__.py index 46fb8bf59f5..69b717e618b 100644 --- a/addons/hr_holidays/report/__init__.py +++ b/addons/hr_holidays/report/__init__.py @@ -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 report_all_leaves diff --git a/addons/hr_holidays/report/holidays_summary_report.py b/addons/hr_holidays/report/holidays_summary_report.py index 3b5df55d916..1520bffb99f 100644 --- a/addons/hr_holidays/report/holidays_summary_report.py +++ b/addons/hr_holidays/report/holidays_summary_report.py @@ -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,8 @@ 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) + # TODO: See if that is the correct type + holidays = self.env['hr.leave'].browse(self.ids) return { 'doc_ids': self.ids, 'doc_model': holidays_report.model, diff --git a/addons/hr_holidays/report/hr_holidays_reports.xml b/addons/hr_holidays/report/hr_holidays_reports.xml index 907112eb7e0..7c3a35eee6a 100644 --- a/addons/hr_holidays/report/hr_holidays_reports.xml +++ b/addons/hr_holidays/report/hr_holidays_reports.xml @@ -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" diff --git a/addons/hr_holidays/report/hr_holidays_views.xml b/addons/hr_holidays/report/hr_holidays_views.xml index 7324619e3fa..d12f7e2bfba 100644 --- a/addons/hr_holidays/report/hr_holidays_views.xml +++ b/addons/hr_holidays/report/hr_holidays_views.xml @@ -2,12 +2,11 @@ <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="model">hr.leave.report</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> @@ -16,20 +15,29 @@ <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="model">hr.leave.report</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="view_holiday_calendar" model="ir.ui.view"> + <field name="name">hr.holidays.report.calendar</field> + <field name="model">hr.leave.report</field> + <field name="arch" type="xml"> + <calendar 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="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="res_model">hr.leave.report</field> <field name="view_type">form</field> <field name="view_mode">graph,pivot,calendar,form</field> <field name="view_id"></field> <!-- force empty --> @@ -52,8 +60,156 @@ </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"/> + <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> + + <menuitem + id="menu_open_company_allocation" + name="Leaves Summary" + parent="menu_hr_holidays_my_leaves" + action="open_company_allocation" + sequence="21"/> + </odoo> diff --git a/addons/hr_holidays/report/report_all_leaves.py b/addons/hr_holidays/report/report_all_leaves.py new file mode 100644 index 00000000000..acca821f58a --- /dev/null +++ b/addons/hr_holidays/report/report_all_leaves.py @@ -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 + ); + """) diff --git a/addons/hr_holidays/security/hr_holidays_security.xml b/addons/hr_holidays/security/hr_holidays_security.xml index 16a2f22c01b..18550930f3a 100644 --- a/addons/hr_holidays/security/hr_holidays_security.xml +++ b/addons/hr_holidays/security/hr_holidays_security.xml @@ -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> diff --git a/addons/hr_holidays/security/ir.model.access.csv b/addons/hr_holidays/security/ir.model.access.csv index 56b3305aa91..6238cdf051a 100644 --- a/addons/hr_holidays/security/ir.model.access.csv +++ b/addons/hr_holidays/security/ir.model.access.csv @@ -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 diff --git a/addons/hr_holidays/tests/test_holidays_flow.py b/addons/hr_holidays/tests/test_holidays_flow.py index 21c98693f05..dfa1d3dea45 100644 --- a/addons/hr_holidays/tests/test_holidays_flow.py +++ b/addons/hr_holidays/tests/test_holidays_flow.py @@ -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. diff --git a/addons/hr_holidays/views/hr_holidays_views.xml b/addons/hr_holidays/views/hr_holidays_views.xml index 3d08d494823..6a6f22ef263 100644 --- a/addons/hr_holidays/views/hr_holidays_views.xml +++ b/addons/hr_holidays/views/hr_holidays_views.xml @@ -4,7 +4,7 @@ <!-- 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="model">hr.leave</field> <field name="arch" type="xml"> <graph string="Appraisal Analysis" stacked="True"> <field name="employee_id" type="row"/> @@ -15,16 +15,51 @@ </field> </record> + <record id="view_hr_holidays_filter_allocations" 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="view_hr_holidays_filter" model="ir.ui.view"> <field name="name">hr.holidays.filter</field> - <field name="model">hr.holidays</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 allocations and requests that belong to an leave type that is 'active' (active field is True)"/> + <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/> @@ -36,12 +71,10 @@ <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"/> + domain="[('holiday_status_id.active', '=', True)]" help="Active Leaves"/> <separator/> - <filter string="My Leaves" name="my_leaves" domain="[('user_id', '=', uid)]"/> + <filter string="My Leaves" name="my_leaves" domain="[('employee_id.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"/> @@ -63,7 +96,7 @@ <record id="view_holiday_new_calendar" model="ir.ui.view"> <field name="name">Leave Request</field> - <field name="model">hr.holidays</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"/> @@ -71,14 +104,59 @@ </field> </record> - <!-- Holidays: Allocation Request --> - <record id="edit_holiday_new" model="ir.ui.view"> + <record id="edit_holiday_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="edit_holiday_new_request" model="ir.ui.view"> <field name="name">Leave Request</field> - <field name="model">hr.holidays</field> + <field name="model">hr.leave</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"/> @@ -98,10 +176,10 @@ <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"/> + <div> + <field name="date_from" class="oe_inline"/> <label string="-" class="oe_inline"/> - <field name="date_to" attrs="{'required':[('type', '=', 'remove')]}" class="oe_inline"/> + <field name="date_to" class="oe_inline"/> </div> <div> <field name="number_of_days_temp" class="oe_inline"/> days @@ -109,14 +187,13 @@ </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="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': [('type', '=', 'remove'),('state','!=','draft'), ('state','!=','confirm')], 'invisible':[('holiday_type','!=','category')]}"/> + <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" attrs="{'invisible':[('type','=','add')]}" widget="toggle_button"/> + <field name="payslip_status" groups="hr_holidays.group_hr_holidays_manager" 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')]}"> + <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> @@ -131,17 +208,16 @@ </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="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="date_from"/> - <field name="date_to"/> <field name="message_needaction" invisible="1"/> <field name="state"/> </tree> @@ -150,7 +226,7 @@ <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="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"> @@ -165,36 +241,32 @@ </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="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="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="model">hr.leave.allocation</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="employee_id"/> + <field name="category_id" invisible="1"/> + <field name="department_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="holiday_status_id"/> <field name="state"/> </tree> </field> @@ -202,12 +274,10 @@ <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="model">hr.leave.allocation</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> @@ -231,19 +301,9 @@ </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 t-attf-class="oe_kanban_bottom_left"> </div> - <div t-attf-class="oe_kanban_bottom_right #{record.date_from.value ? 'mt8': ''}"> + <div t-attf-class="oe_kanban_bottom_right"> <span class="badge"><t t-esc="record.number_of_days.value"/> days</span> </div> </div> @@ -256,7 +316,7 @@ <record id="view_holiday" model="ir.ui.view"> <field name="name">hr.holidays.tree</field> - <field name="model">hr.holidays</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"> @@ -280,11 +340,11 @@ <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="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'), ('type', '=', 'remove'), ('state', '!=', 'refuse')]</field> + <field name="domain">[('holiday_type','=','employee'), ('state', '!=', 'refuse')]</field> <field name="search_view_id" ref="view_hr_holidays_filter"/> </record> @@ -325,13 +385,10 @@ <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="res_model">hr.leave</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="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"> @@ -355,7 +412,7 @@ <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="view_id" ref="edit_holiday_new_request"/> <field name="act_window_id" ref="open_ask_holidays"/> </record> @@ -374,14 +431,12 @@ <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="res_model">hr.leave</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="view_id" ref="edit_holiday_new_allocation"/> <field name="search_view_id" ref="view_hr_holidays_filter"/> </record> @@ -395,26 +450,23 @@ <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="view_id" ref="edit_holiday_new_allocation"/> <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="res_model">hr.leave.allocation</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"/> + <field name="domain">[('employee_id.user_id', '=', uid)]</field> + <field name="view_id" ref="edit_holiday_new_allocation"/> + <field name="search_view_id" ref="view_hr_holidays_filter_allocations"/> </record> <record id="action_open_allocation_holidays_tree" model="ir.actions.act_window.view"> @@ -427,7 +479,7 @@ <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="view_id" ref="edit_holiday_new_allocation"/> <field name="act_window_id" ref="open_allocation_holidays"/> </record> @@ -439,15 +491,13 @@ <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="res_model">hr.leave.allocation</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"/> + <field name="view_id" ref="edit_holiday_new_allocation"/> + <field name="search_view_id" ref="view_hr_holidays_filter_allocations"/> </record> <record id="action_request_approve_allocation_tree" model="ir.actions.act_window.view"> @@ -460,54 +510,27 @@ <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="view_id" ref="edit_holiday_new_allocation"/> <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="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="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"> + <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="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> @@ -516,7 +539,6 @@ 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> @@ -528,19 +550,18 @@ action="open_department_holidays_approve" sequence="1"/> - <record id="open_department_holidays_allocation_approve" model="ir.actions.act_window"> + <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="res_model">hr.leave.allocation</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="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="domain">[('type','=','add')]</field> - <field name="search_view_id" ref="view_hr_holidays_filter"/> + <field name="search_view_id" ref="view_hr_holidays_filter_allocations"/> </record> <menuitem @@ -559,8 +580,8 @@ <!-- 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="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"/> @@ -570,8 +591,8 @@ </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="name">hr.leave.type.form</field> + <field name="model">hr.leave.type</field> <field name="arch" type="xml"> <form string="Leave Type"> <sheet> @@ -599,8 +620,8 @@ </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="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"/> @@ -612,8 +633,8 @@ </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="name">hr.leave.type.kanban</field> + <field name="model">hr.leave.type</field> <field name="arch" type="xml"> <kanban class="o_kanban_mobile"> <templates> @@ -634,8 +655,8 @@ </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="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"> @@ -646,8 +667,8 @@ </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="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"/> @@ -659,7 +680,7 @@ <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="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"/> @@ -678,20 +699,20 @@ <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="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_holidays_filter"/> + <field name="search_view_id" ref="view_hr_holidays_filter_allocations"/> </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="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> @@ -731,33 +752,29 @@ <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="res_model">hr.leave</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="res_model">hr.leave.allocation</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"/> + <field name="search_view_id" ref="view_hr_holidays_filter_allocations"/> </record> <record id="hr_employee_action_from_department" model="ir.actions.act_window"> @@ -775,7 +792,7 @@ <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="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> @@ -784,7 +801,7 @@ <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="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> diff --git a/addons/l10n_fr_hr_payroll/data/l10n_fr_hr_payroll_data.xml b/addons/l10n_fr_hr_payroll/data/l10n_fr_hr_payroll_data.xml index 932c5b808d9..81ed5cbe0d8 100644 --- a/addons/l10n_fr_hr_payroll/data/l10n_fr_hr_payroll_data.xml +++ b/addons/l10n_fr_hr_payroll/data/l10n_fr_hr_payroll_data.xml @@ -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> diff --git a/addons/project_timesheet_holidays/__init__.py b/addons/project_timesheet_holidays/__init__.py index cb09489a1e7..d553cb8e270 100644 --- a/addons/project_timesheet_holidays/__init__.py +++ b/addons/project_timesheet_holidays/__init__.py @@ -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, }) diff --git a/addons/project_timesheet_holidays/models/account_analytic.py b/addons/project_timesheet_holidays/models/account_analytic.py index b0472a515be..0fd5788df3d 100644 --- a/addons/project_timesheet_holidays/models/account_analytic.py +++ b/addons/project_timesheet_holidays/models/account_analytic.py @@ -8,7 +8,8 @@ from odoo.exceptions import UserError class AccountAnalyticLine(models.Model): _inherit = 'account.analytic.line' - holiday_id = fields.Many2one("hr.holidays", string='Leave Request') + # TODO: See if it is the right type + holiday_id = fields.Many2one("hr.leave", string='Leave Request') @api.multi def unlink(self): diff --git a/addons/project_timesheet_holidays/models/hr_holidays.py b/addons/project_timesheet_holidays/models/hr_holidays.py index 2d245e834d9..96ac9446313 100644 --- a/addons/project_timesheet_holidays/models/hr_holidays.py +++ b/addons/project_timesheet_holidays/models/hr_holidays.py @@ -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 diff --git a/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py b/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py index 9d358c14114..b7b7b6fc3fb 100644 --- a/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py +++ b/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py @@ -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, diff --git a/addons/project_timesheet_holidays/views/hr_holidays_views.xml b/addons/project_timesheet_holidays/views/hr_holidays_views.xml index 27af36b85f8..1e010067a57 100644 --- a/addons/project_timesheet_holidays/views/hr_holidays_views.xml +++ b/addons/project_timesheet_holidays/views/hr_holidays_views.xml @@ -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"> |
