From df324c885771814efde7918cfecfa7940a38591f Mon Sep 17 00:00:00 2001 From: RomainLibert Date: Thu, 8 Feb 2018 09:32:44 +0100 Subject: [PATCH] [IMP] hr_holidays: Improve leave type: limit date, visibility, usability In order to help limit leaves recording errors. We need to add some configuration on leave type object. For example we need to avoid people taking legal leaves 2016 on 2017. * Add validity dates : start and end dates on the leave type. An empty end date means forever * Double validation : change the checkbox into a radio button with now three choices : - Human Resource Responsible - Manager - Double Validation * Add a sequence field, using handle widget * Add a field, to specify if the employee can select the leave type in his allocations, requests or in both of them --- addons/hr_holidays/data/hr_holidays_data.xml | 4 + addons/hr_holidays/models/hr.py | 2 +- addons/hr_holidays/models/hr_leave.py | 53 ++++++++++-- .../hr_holidays/models/hr_leave_allocation.py | 46 ++++++++-- addons/hr_holidays/models/hr_leave_type.py | 52 +++++++++++- addons/hr_holidays/tests/common.py | 18 ++++ .../hr_holidays/tests/test_holidays_flow.py | 83 +++++++++++++++++-- .../hr_holidays/views/hr_leave_type_views.xml | 23 ++++- addons/hr_holidays/views/hr_leave_views.xml | 2 +- 9 files changed, 250 insertions(+), 33 deletions(-) diff --git a/addons/hr_holidays/data/hr_holidays_data.xml b/addons/hr_holidays/data/hr_holidays_data.xml index 235bd6e036d..7213fdd66a4 100644 --- a/addons/hr_holidays/data/hr_holidays_data.xml +++ b/addons/hr_holidays/data/hr_holidays_data.xml @@ -7,6 +7,8 @@ black + + @@ -21,6 +23,8 @@ Compensatory Days lavender + + diff --git a/addons/hr_holidays/models/hr.py b/addons/hr_holidays/models/hr.py index 3f70bec2961..a30175abbca 100644 --- a/addons/hr_holidays/models/hr.py +++ b/addons/hr_holidays/models/hr.py @@ -142,7 +142,7 @@ class Employee(models.Model): 'number_of_days_temp': difference }) leave.action_approve() - if leave.double_validation: + if leave.validation_type == 'both': leave.action_validate() elif difference < 0: raise UserError(_('You cannot reduce validated allocation requests')) diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 2f6c5ee61c7..30ebc057333 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -8,7 +8,7 @@ import math from datetime import timedelta from odoo import api, fields, models -from odoo.exceptions import UserError, AccessError, ValidationError +from odoo.exceptions import UserError, ValidationError from odoo.tools import float_compare from odoo.tools.translate import _ @@ -22,9 +22,20 @@ class HolidaysRequest(models.Model): _order = "date_from desc" _inherit = ['mail.thread'] + @api.model + def default_get(self, fields_list): + defaults = super(HolidaysRequest, self).default_get(fields_list) + + LeaveType = self.env['hr.leave.type'].with_context(employee_id=defaults.get('employee_id'), default_date_from=defaults.get('date_from')) + lt = LeaveType.search([('valid', '=', True), ('employee_applicability', 'in', ['leave', 'both'])]) + + defaults['holiday_status_id'] = lt[0].id if len(lt) > 0 else defaults.get('holiday_status_id') + return defaults + 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'), @@ -47,7 +58,8 @@ class HolidaysRequest(models.Model): 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.leave.type", string="Leave Type", required=True, readonly=True, - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, + domain="[('valid', '=', True), ('employee_applicability', 'in', ['leave', 'both'])]") 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') manager_id = fields.Many2one('hr.employee', related='employee_id.parent_id', string='Manager', readonly=True, store=True) @@ -75,7 +87,7 @@ class HolidaysRequest(models.Model): 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') + validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type') can_reset = fields.Boolean('Can reset', compute='_compute_can_reset') _sql_constraints = [ @@ -208,6 +220,20 @@ class HolidaysRequest(models.Model): if employee.user_id: self.message_subscribe_users(user_ids=employee.user_id.ids) + @api.multi + @api.constrains('holiday_status_id') + def _check_leave_type_validity(self): + for leave in self: + if leave.holiday_status_id.validity_start and leave.holiday_status_id.validity_stop: + vstart = fields.Datetime.from_string(leave.holiday_status_id.validity_start) + vstop = fields.Datetime.from_string(leave.holiday_status_id.validity_stop) + dfrom = fields.Datetime.from_string(leave.date_from) + dto = fields.Datetime.from_string(leave.date_to) + + if dfrom and dto and (dfrom < vstart or dto > vstop): + raise UserError(_('You can take %s only between %s and %s') % (leave.holiday_status_id.display_name, \ + leave.holiday_status_id.validity_start, leave.holiday_status_id.validity_stop)) + @api.model def create(self, values): """ Override to avoid automatic logging of creation """ @@ -331,8 +357,8 @@ class HolidaysRequest(models.Model): @api.multi def action_approve(self): - # if double_validation: this method is the first approval approval - # if not double_validation: this method calls action_validate() below + # if validation_type == 'both': this method is the first approval approval + # if validation_type != 'both': this method calls action_validate() below if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'): raise UserError(_('Only an HR Officer or Manager can approve leave requests.')) @@ -340,8 +366,17 @@ class HolidaysRequest(models.Model): 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() + for holiday in self: + validation_type = holiday.holiday_status_id.validation_type + manager = holiday.employee_id.parent_id or holiday.employee_id.department_id.manager_id + if (validation_type in ['manager', 'both']) and (manager and manager != current_employee)\ + and not self.env.user.has_group('hr_holidays.group_hr_holidays_manager'): + raise UserError(_('You must be %s manager to approve this leave') % (holiday.employee_id.name)) + elif validation_type == 'hr' and not self.env.user.has_group('hr_holidays.group_hr_holidays_manager'): + raise UserError(_('You must be a Human Resource Manager to approve this Leave')) + + self.filtered(lambda hol: hol.validation_type == 'both').write({'state': 'validate1', 'first_approver_id': current_employee.id}) + self.filtered(lambda hol: not hol.validation_type == 'both').action_validate() return True @api.multi @@ -357,7 +392,7 @@ class HolidaysRequest(models.Model): raise UserError(_('Only an HR Manager can apply the second approval on leave requests.')) holiday.write({'state': 'validate'}) - if holiday.double_validation: + if holiday.validation_type == 'both': holiday.write({'second_approver_id': current_employee.id}) else: holiday.write({'first_approver_id': current_employee.id}) @@ -371,7 +406,7 @@ class HolidaysRequest(models.Model): 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: + if leaves and leaves[0].validation_type == 'both': leaves.action_validate() return True diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 9eac9e9ff66..583e01ac74c 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -6,7 +6,7 @@ import logging from odoo import api, fields, models -from odoo.exceptions import UserError, AccessError +from odoo.exceptions import UserError from odoo.tools.translate import _ _logger = logging.getLogger(__name__) @@ -20,6 +20,11 @@ class HolidaysAllocation(models.Model): 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) + def _default_holiday_status_id(self): + LeaveType = self.env['hr.leave.type'].with_context(employee_id=self._default_employee().id) + lt = LeaveType.search([('valid', '=', True), ('employee_applicability', 'in', ['leave', 'both']), ('limit', '=', False)]) + return lt[:1] + name = fields.Char('Description') state = fields.Selection([ ('draft', 'To Submit'), @@ -34,7 +39,8 @@ class HolidaysAllocation(models.Model): "\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)]}) + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, + domain="[('valid', '=', True), ('employee_applicability', 'in', ['allocation', 'both']), ('limit', '=', False)]", default=_default_holiday_status_id) 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)]}) @@ -59,7 +65,7 @@ class HolidaysAllocation(models.Model): 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') + validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type') can_reset = fields.Boolean('Can reset', compute='_compute_can_reset') _sql_constraints = [ @@ -120,6 +126,19 @@ class HolidaysAllocation(models.Model): if employee.user_id: self.message_subscribe_users(user_ids=employee.user_id.ids) + @api.multi + @api.constrains('holiday_status_id') + def _check_leave_type_validity(self): + for allocation in self: + if allocation.holiday_status_id.validity_start and allocation.holiday_status_id.validity_stop: + vstart = fields.Datetime.from_string(allocation.holiday_status_id.validity_start) + vstop = fields.Datetime.from_string(allocation.holiday_status_id.validity_stop) + today = fields.Datetime.from_string(fields.Datetime.now()) + + if vstart > today or vstop < today: + raise UserError(_('You can allocate %s only between %s and %s') % (allocation.holiday_status_id.display_name, + allocation.holiday_status_id.validity_start, allocation.holiday_status_id.validity_stop)) + @api.model def create(self, values): """ Override to avoid automatic logging of creation """ @@ -191,8 +210,8 @@ class HolidaysAllocation(models.Model): @api.multi def action_approve(self): - # if double_validation: this method is the first approval approval - # if not double_validation: this method calls action_validate() below + # if validation_type == 'both': this method is the first approval approval + # if validation_type != 'both': this method calls action_validate() below if not self.env.user.has_group('hr_holidays.group_hr_holidays_user'): raise UserError(_('Only an HR Officer or Manager can approve leave requests.')) @@ -200,8 +219,17 @@ class HolidaysAllocation(models.Model): 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() + for holiday in self: + validation_type = holiday.holiday_status_id.validation_type + manager = holiday.employee_id.parent_id or holiday.employee_id.department_id.manager_id + if (validation_type in ['manager', 'both']) and (manager and manager != current_employee)\ + and not self.env.user.has_group('hr_holidays.group_hr_holidays_manager'): + raise UserError(_('You must be %s manager to approve this leave') % (holiday.employee_id.name)) + elif validation_type == 'hr' and not self.env.user.has_group('hr_holidays.group_hr_holidays_manager'): + raise UserError(_('You must be a Human Resource Manager to approve this Leave')) + + self.filtered(lambda hol: hol.validation_type == 'both').write({'state': 'validate1', 'first_approver_id': current_employee.id}) + self.filtered(lambda hol: not hol.validation_type == 'both').action_validate() return True @api.multi @@ -217,7 +245,7 @@ class HolidaysAllocation(models.Model): raise UserError(_('Only an HR Manager can apply the second approval on leave requests.')) holiday.write({'state': 'validate'}) - if holiday.double_validation: + if holiday.validation_type == 'both': holiday.write({'second_approver_id': current_employee.id}) else: holiday.write({'first_approver_id': current_employee.id}) @@ -229,7 +257,7 @@ class HolidaysAllocation(models.Model): 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: + if leaves and leaves[0].validation_type == 'both': leaves.action_validate() return True diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py index f916000b10d..a7db3f2ff48 100644 --- a/addons/hr_holidays/models/hr_leave_type.py +++ b/addons/hr_holidays/models/hr_leave_type.py @@ -6,6 +6,7 @@ import logging from odoo import api, fields, models +from odoo.exceptions import ValidationError from odoo.tools.translate import _ _logger = logging.getLogger(__name__) @@ -14,8 +15,11 @@ _logger = logging.getLogger(__name__) class HolidaysType(models.Model): _name = "hr.leave.type" _description = "Leave Type" + _order = "sequence, id" name = fields.Char('Leave Type', required=True, translate=True) + sequence = fields.Integer(default=100, + help='The type with the smallest sequence is the default value in leave request') categ_id = fields.Many2one('calendar.event.type', string='Meeting Type', help='Once a leave is validated, Odoo will create a corresponding meeting of this type in the calendar.') color_name = fields.Selection([ @@ -52,10 +56,54 @@ class HolidaysType(models.Model): virtual_remaining_leaves = fields.Float(compute='_compute_leaves', string='Virtual Remaining Leaves', help='Maximum Leaves Allowed - Leaves Already Taken - Leaves Waiting Approval') - double_validation = fields.Boolean(string='Apply Double Validation', - help="When selected, the Allocation/Leave Requests for this type require a second validation to be approved.") company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id) + validation_type = fields.Selection([('hr', 'Human Resource Responsible'), + ('manager', 'Manager'), + ('both', 'Double Validation')], + default='hr', + string='Validation By') + + employee_applicability = fields.Selection([('both', 'On Leave As Well As On Allocation'), + ('leave', 'Only On Leave'), + ('allocation', 'Only On Allocation')], + default='both', string='Available For Employee :', + help='This leave type will be available on Leave / Allocation request based on selected value') + + validity_start = fields.Date("Start Date", default=fields.Date.today(), + help='Adding validity to types of leaves so that it cannot be selected outside' + 'this time period') + validity_stop = fields.Date("End Date") + + valid = fields.Boolean(compute='_compute_valid', search='_search_valid', help='This indicates if it is still possible to use this type of leave') + + @api.multi + @api.constrains('validity_start', 'validity_stop') + def _check_validity_dates(self): + for htype in self: + if htype.validity_start and htype.validity_stop and \ + htype.validity_start > htype.validity_stop: + raise ValidationError(_("End of validity period should be greater than start of validity period")) + + @api.multi + @api.depends('validity_start', 'validity_stop', 'limit') + def _compute_valid(self): + dt = self._context.get('default_date_from', fields.Date.today()) + + for holiday_type in self: + if holiday_type.validity_start and holiday_type.validity_stop: + holiday_type.valid = ((dt < holiday_type.validity_stop) and (dt > holiday_type.validity_start)) + else: + holiday_type.valid = not holiday_type.validity_stop + + def _search_valid(self, operator, value): + dt = self._context.get('default_date_from', fields.Date.today()) + signs = ['>=', '<='] if operator == '=' else ['<=', '>='] + + return ['|', ('validity_stop', operator, False), '&', + ('validity_stop', signs[0] if value else signs[1], dt), + ('validity_start', signs[1] if value else signs[0], dt)] + @api.multi def get_days(self, employee_id): # need to use `dict` constructor to create a dict per id diff --git a/addons/hr_holidays/tests/common.py b/addons/hr_holidays/tests/common.py index 85dff9ba5ff..8ecba9ed7d2 100644 --- a/addons/hr_holidays/tests/common.py +++ b/addons/hr_holidays/tests/common.py @@ -35,11 +35,29 @@ class TestHrHolidaysBase(common.TransactionCase): }).id # Hr Data + Department = self.env['hr.department'].with_context(tracking_disable=True) + + self.hr_dept = Department.create({ + 'name': 'Human Resources', + }) + self.rd_dept = Department.create({ + 'name': 'Research and devlopment', + }) + self.employee_emp_id = self.env['hr.employee'].create({ 'name': 'David Employee', 'user_id': self.user_employee_id, + 'department_id': self.rd_dept.id, }).id self.employee_hruser_id = self.env['hr.employee'].create({ 'name': 'Armande HrUser', 'user_id': self.user_hruser_id, + 'department_id': self.rd_dept.id, }).id + self.employee_hrmanager_id = self.env['hr.employee'].create({ + 'name': 'Bastien HrManager', + 'user_id': self.user_hrmanager_id, + 'department_id': self.hr_dept.id, + }).id + + self.rd_dept.write({'manager_id': self.employee_hruser_id}) diff --git a/addons/hr_holidays/tests/test_holidays_flow.py b/addons/hr_holidays/tests/test_holidays_flow.py index dfa1d3dea45..2bf1c819f88 100644 --- a/addons/hr_holidays/tests/test_holidays_flow.py +++ b/addons/hr_holidays/tests/test_holidays_flow.py @@ -3,6 +3,7 @@ from datetime import datetime from dateutil.relativedelta import relativedelta +from odoo import fields from odoo.exceptions import AccessError, ValidationError, UserError from odoo.tools import mute_logger, test_reports @@ -43,13 +44,26 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'categ_id': self.env['calendar.event.type'].sudo(self.user_hrmanager_id).create({'name': 'NotLimitedMeetingType'}).id }) self.holidays_status_1 = HolidayStatusManagerGroup.create({ - 'name': 'NotLimited', + 'name': 'NotLimitedHR', 'limit': True, + 'validation_type': 'hr', }) self.holidays_status_2 = HolidayStatusManagerGroup.create({ 'name': 'Limited', 'limit': False, - 'double_validation': True, + 'validation_type': 'both', + }) + self.holidays_status_3 = HolidayStatusManagerGroup.create({ + 'name': 'NotLimitedManager', + 'limit': True, + 'validation_type': 'manager', + }) + self.holiday_status_4 = HolidayStatusManagerGroup.create({ + 'name': 'TimeNotLimited', + 'limit': True, + 'validation_type': 'manager', + 'validity_start': fields.Datetime.from_string('2017-01-01 00:00:00'), + 'validity_stop': fields.Datetime.from_string('2017-06-01 00:00:00'), }) # -------------------------------------------------- @@ -69,7 +83,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): }) Requests.search([('name', '=', 'Hol10')]).unlink() - # Employee creates a leave request in a no-limit category + # Employee creates a leave request in a no-limit category hr manager only hol1_employee_group = HolidaysEmployeeGroup.create({ 'name': 'Hol11', 'employee_id': self.employee_emp_id, @@ -79,15 +93,43 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'number_of_days_temp': 1, }) hol1_user_group = hol1_employee_group.sudo(self.user_hruser_id) + hol1_manager_group = hol1_employee_group.sudo(self.user_hrmanager_id) self.assertEqual(hol1_user_group.state, 'confirm', 'hr_holidays: newly created leave request should be in confirm state') # Employee validates its leave request -> should not work with self.assertRaises(UserError): hol1_employee_group.action_approve() - self.assertEqual(hol1_user_group.state, 'confirm', 'hr_holidays: employee should not be able to validate its own leave request') + self.assertEqual(hol1_manager_group.state, 'confirm', 'hr_holidays: employee should not be able to validate its own leave request') + + # HrUser validates the employee leave request -> should not work + with self.assertRaises(UserError): + hol1_user_group.action_approve() + self.assertEqual(hol1_manager_group.state, 'confirm', 'hr_holidays: hr user should not be able to validate manager only leaves') + + # HrManager validates the employee leave request + hol1_manager_group.action_approve() + self.assertEqual(hol1_manager_group.state, 'validate', 'hr_holidays: validates leave request should be in validate state') + + # Employee creates a leave request in a no-limit category department manager only + hol12_employee_group = HolidaysEmployeeGroup.create({ + 'name': 'Hol12', + 'employee_id': self.employee_emp_id, + 'holiday_status_id': self.holidays_status_3.id, + 'date_from': (datetime.today() + relativedelta(days=12)), + 'date_to': (datetime.today() + relativedelta(days=13)), + 'number_of_days_temp': 1, + }) + hol12_user_group = hol12_employee_group.sudo(self.user_hruser_id) + hol12_manager_group = hol12_employee_group.sudo(self.user_hrmanager_id) + self.assertEqual(hol12_user_group.state, 'confirm', 'hr_holidays: newly created leave request should be in confirm state') + + # Employee validates its leave request -> should not work + with self.assertRaises(UserError): + hol12_employee_group.action_approve() + self.assertEqual(hol12_user_group.state, 'confirm', 'hr_holidays: employee should not be able to validate its own leave request') # HrUser validates the employee leave request - hol1_user_group.action_approve() + hol12_user_group.action_approve() self.assertEqual(hol1_user_group.state, 'validate', 'hr_holidays: validates leave request should be in validate state') # -------------------------------------------------- @@ -128,6 +170,9 @@ class TestHolidaysFlow(TestHrHolidaysBase): }) # HrUser validates the first step aloc1_user_group.action_approve() + # HrUser validates the second step -> should crash + with self.assertRaises(UserError): + aloc1_user_group.action_validate() # HrManager validates the second step aloc1_user_group.sudo(self.user_hrmanager_id).action_validate() # Checks Employee has effectively some days left @@ -147,11 +192,14 @@ class TestHolidaysFlow(TestHrHolidaysBase): # Check left days: - 1 virtual remaining day _check_holidays_status(hol_status_2_employee_group, 2.0, 0.0, 2.0, 1.0) - # HrUser validates the first step - hol2_user_group.action_approve() + # HrManager validates the first step + hol2_user_group.sudo(self.user_hrmanager_id).action_approve() self.assertEqual(hol2.state, 'validate1', 'hr_holidays: first validation should lead to validate1 state') + # HrUser validates the second step -> should crash + with self.assertRaises(UserError): + hol2_user_group.action_validate() # HrManager validates the second step hol2_user_group.sudo(self.user_hrmanager_id).action_validate() self.assertEqual(hol2.state, 'validate', @@ -197,7 +245,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): '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, - 'number_of_days_temp': 1 + 'number_of_days_temp': 1, }) # I find a small mistake on my leave request to I click on "Refuse" button to correct a mistake. hol3.action_refuse() @@ -213,6 +261,25 @@ class TestHolidaysFlow(TestHrHolidaysBase): # Check left days for casual leave: 19 days left _check_holidays_status(hol3_status, 20.0, 1.0, 19.0, 19.0) + Requests.create({ + 'name': 'Sick Leave', + 'holiday_status_id': self.holiday_status_4.id, + 'date_from': fields.Datetime.from_string('2017-03-03 06:00:00'), + 'date_to': fields.Datetime.from_string('2017-03-11 19:00:00'), + 'employee_id': employee_id, + 'number_of_days_temp': 1, + }).unlink() + + with self.assertRaises(ValidationError): + Requests.create({ + 'name': 'Sick Leave', + 'holiday_status_id': self.holiday_status_4.id, + 'date_from': fields.Datetime.from_string('2017-07-03 06:00:00'), + 'date_to': fields.Datetime.from_string('2017-07-11 19:00:00'), + 'employee_id': employee_id, + 'number_of_days_temp': 1, + }) + def test_10_leave_summary_reports(self): # Print the HR Holidays(Summary Department) Report through the wizard ctx = { diff --git a/addons/hr_holidays/views/hr_leave_type_views.xml b/addons/hr_holidays/views/hr_leave_type_views.xml index da4e973f70a..d5ae5093123 100644 --- a/addons/hr_holidays/views/hr_leave_type_views.xml +++ b/addons/hr_holidays/views/hr_leave_type_views.xml @@ -28,14 +28,26 @@ - - - + + + + + + + + + + + + + + + @@ -83,8 +95,13 @@ 35 + + + + + diff --git a/addons/hr_holidays/views/hr_leave_views.xml b/addons/hr_holidays/views/hr_leave_views.xml index 649410c283f..c985ee037e0 100644 --- a/addons/hr_holidays/views/hr_leave_views.xml +++ b/addons/hr_holidays/views/hr_leave_views.xml @@ -91,7 +91,7 @@ - +