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 | |
| 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.
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"> |
