diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index d65c66855f0cb..8a26d786625ef 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -295,9 +295,9 @@ def _auto_init(self): @api.constrains('holiday_status_id', 'number_of_days') def _check_allocation_duration(self): - for holiday in self: - if holiday.holiday_status_id.requires_allocation == 'yes' and holiday.holiday_allocation_id and holiday.number_of_days > holiday.holiday_allocation_id.number_of_days: - raise ValidationError(_("You have several allocations for those type and period.\nPlease split your request to fit in their number of days.")) + # Deprecated as part of https://github.com/odoo/odoo/pull/96545 + # TODO: remove in master + return @api.depends_context('uid') def _compute_description(self): @@ -336,49 +336,9 @@ def _compute_state(self): @api.depends('holiday_status_id.requires_allocation', 'validation_type', 'employee_id', 'date_from', 'date_to') def _compute_from_holiday_status_id(self): - invalid_self = self.filtered(lambda leave: not leave.date_to or not leave.date_from) - if invalid_self: - invalid_self.update({'holiday_allocation_id': False}) - self = self - invalid_self - if not self: - return - allocations = self.env['hr.leave.allocation'].search_read( - [ - ('holiday_status_id', 'in', self.holiday_status_id.ids), - ('employee_id', 'in', self.employee_id.ids), - ('state', '=', 'validate'), - '|', - ('date_to', '>=', min(self.mapped('date_to'))), - '&', - ('date_to', '=', False), - ('date_from', '<=', max(self.mapped('date_from'))), - ], ['id', 'date_from', 'date_to', 'holiday_status_id', 'employee_id', 'max_leaves', 'taken_leave_ids'], order="date_to, id" - ) - allocations_dict = defaultdict(lambda: []) - for allocation in allocations: - allocation['taken_leaves'] = self.env['hr.leave'].browse(allocation.pop('taken_leave_ids'))\ - .filtered(lambda leave: leave.state in ['confirm', 'validate', 'validate1']) - allocations_dict[(allocation['holiday_status_id'][0], allocation['employee_id'][0])].append(allocation) - - for leave in self: - if leave.holiday_status_id.requires_allocation == 'yes' and leave.date_from and leave.date_to: - found_allocation = False - date_to = leave.date_to.replace(tzinfo=UTC).astimezone(timezone(leave.tz)).date() - date_from = leave.date_from.replace(tzinfo=UTC).astimezone(timezone(leave.tz)).date() - leave_unit = 'number_of_%s_display' % ('hours' if leave.leave_type_request_unit == 'hour' else 'days') - for allocation in allocations_dict[(leave.holiday_status_id.id, leave.employee_id.id)]: - date_to_check = allocation['date_to'] >= date_to if allocation['date_to'] else True - date_from_check = allocation['date_from'] <= date_from - if (date_to_check and date_from_check): - allocation_taken_leaves = allocation['taken_leaves'] - leave - allocation_taken_number_of_units = sum(allocation_taken_leaves.mapped(leave_unit)) - leave_number_of_units = leave[leave_unit] - if allocation['max_leaves'] >= allocation_taken_number_of_units + leave_number_of_units: - found_allocation = allocation['id'] - break - leave.holiday_allocation_id = self.env['hr.leave.allocation'].browse(found_allocation) if found_allocation else False - else: - leave.holiday_allocation_id = False + # Deprecated as part of https://github.com/odoo/odoo/pull/96545 + # TODO: remove in master + self.holiday_allocation_id = False @api.depends('request_date_from_period', 'request_hour_from', 'request_hour_to', 'request_date_from', 'request_date_to', 'request_unit_half', 'request_unit_hours', 'request_unit_custom', 'employee_id') @@ -668,14 +628,14 @@ def _check_date(self): @api.constrains('state', 'number_of_days', 'holiday_status_id') def _check_holidays(self): + mapped_days = self.holiday_status_id.get_employees_days(self.employee_id.ids) for holiday in self: - if holiday.holiday_type != 'employee' or not holiday.employee_id or not holiday.holiday_status_id or holiday.holiday_status_id.requires_allocation == 'no': + if holiday.holiday_type != 'employee' or not holiday.employee_id or holiday.holiday_status_id.requires_allocation == 'no': continue - mapped_days = holiday.holiday_status_id.get_employees_days([holiday.employee_id.id], holiday.date_from) leave_days = mapped_days[holiday.employee_id.id][holiday.holiday_status_id.id] if float_compare(leave_days['remaining_leaves'], 0, precision_digits=2) == -1 or float_compare(leave_days['virtual_remaining_leaves'], 0, precision_digits=2) == -1: raise ValidationError(_('The number of remaining time off is not sufficient for this time off type.\n' - 'Please also check the time off waiting for validation.') + '\n- %s' % holiday.display_name) + 'Please also check the time off waiting for validation.')) @api.constrains('date_from', 'date_to', 'employee_id') def _check_date_state(self): @@ -803,43 +763,15 @@ def add_follower(self, employee_id): @api.constrains('holiday_allocation_id') def _check_allocation_id(self): - for leave in self: - if leave.holiday_type == 'employee' and not leave.multi_employee and\ - leave.holiday_status_id.requires_allocation == 'yes' and not leave.holiday_allocation_id: - raise ValidationError(_( - 'Could not find an allocation of type %(leave_type)s for the requested time period.', - leave_type=leave.holiday_status_id.display_name, - ) + '\n- %s' % (leave.employee_id.name)) + # Deprecated as part of https://github.com/odoo/odoo/pull/96545 + # TODO: remove in master + return @api.constrains('holiday_allocation_id', 'date_to', 'date_from') def _check_leave_type_validity(self): - for leave in self: - vstart = leave.holiday_allocation_id.date_from - vstop = leave.holiday_allocation_id.date_to - dfrom = leave.date_from - dto = leave.date_to - if vstart and vstop: - if dfrom and dto and (dfrom.date() < vstart or dto.date() > vstop): - raise ValidationError(_( - '%(leave_type)s are only valid between %(start)s and %(end)s', - leave_type=leave.holiday_status_id.display_name, - start=vstart, - end=vstop - )) - elif vstart: - if dfrom and (dfrom.date() < vstart): - raise ValidationError(_( - '%(leave_type)s are only valid starting from %(date)s', - leave_type=leave.holiday_status_id.display_name, - date=vstart - )) - elif vstop: - if dto and (dto.date() > vstop): - raise ValidationError(_( - '%(leave_type)s are only valid until %(date)s', - leave_type=leave.holiday_status_id.display_name, - date=vstop - )) + # Deprecated as part of https://github.com/odoo/odoo/pull/96545 + # TODO: remove in master + return def _check_double_validation_rules(self, employees, state): if self.user_has_groups('hr_holidays.group_hr_holidays_manager'): @@ -882,8 +814,6 @@ def create(self, vals_list): holidays = super(HolidaysRequest, self.with_context(mail_create_nosubscribe=True)).create(vals_list) - holidays.filtered(lambda holiday: not holiday.holiday_allocation_id).with_user(SUPERUSER_ID)._compute_from_holiday_status_id() - for holiday in holidays: if not self._context.get('leave_fast_create'): # Everything that is done here must be done using sudo because we might diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index 70bd4bc82023c..a0f5f4f9aae38 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -193,11 +193,10 @@ def _compute_description_validity(self): @api.depends('employee_id', 'holiday_status_id', 'taken_leave_ids.number_of_days', 'taken_leave_ids.state') def _compute_leaves(self): + employee_days_per_allocation = self.holiday_status_id._get_employees_days_per_allocation(self.employee_id.ids) for allocation in self: allocation.max_leaves = allocation.number_of_hours_display if allocation.type_request_unit == 'hour' else allocation.number_of_days - allocation.leaves_taken = sum(taken_leave.number_of_hours_display if taken_leave.leave_type_request_unit == 'hour' else taken_leave.number_of_days\ - for taken_leave in allocation.taken_leave_ids\ - if taken_leave.state == 'validate') + allocation.leaves_taken = employee_days_per_allocation[allocation.employee_id.id][allocation.holiday_status_id][allocation]['leaves_taken'] @api.depends('number_of_days') def _compute_number_of_days_display(self): diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py index b308f54accb1a..c1a317219dc52 100644 --- a/addons/hr_holidays/models/hr_leave_type.py +++ b/addons/hr_holidays/models/hr_leave_type.py @@ -7,11 +7,13 @@ import logging from collections import defaultdict +from datetime import time, timedelta from odoo import api, fields, models from odoo.osv import expression from odoo.tools.translate import _ from odoo.tools.float_utils import float_round +from odoo.addons.resource.models.resource import Intervals _logger = logging.getLogger(__name__) @@ -212,7 +214,163 @@ def _search_virtual_remaining_leaves(self, operator, value): return [('id', 'in', valid_leave_types.ids)] + def _get_employees_days_per_allocation(self, employee_ids, date=None): + leaves = self.env['hr.leave'].search([ + ('employee_id', 'in', employee_ids), + ('state', 'in', ['confirm', 'validate1', 'validate']), + ('holiday_status_id', 'in', self.ids) + ]) + + allocations = self.env['hr.leave.allocation'].search([ + ('employee_id', 'in', employee_ids), + ('state', 'in', ['validate']), + ('holiday_status_id', 'in', self.ids), + ]) + + if not date: + date = fields.Date.to_date(self.env.context.get('default_date_from')) or fields.Date.context_today(self) + + # The allocation_employees dictionary groups the allocations based on the employee and the holiday type + # The structure is the following: + # - KEYS: + # allocation_employees + # |--employee_id + # |--holiday_status_id + # - VALUES: + # Intervals with the start and end date of each allocation and associated allocations within this interval + allocation_employees = defaultdict(lambda: defaultdict(list)) + + ### Creation of the allocation intervals ### + for holiday_status_id in allocations.holiday_status_id: + for employee_id in employee_ids: + allocation_intervals = Intervals([( + fields.datetime.combine(allocation.date_from, time.min), + fields.datetime.combine(allocation.date_to or datetime.date.max, time.max), + allocation) + for allocation in allocations.filtered(lambda allocation: allocation.employee_id.id == employee_id and allocation.holiday_status_id == holiday_status_id)]) + + allocation_employees[employee_id][holiday_status_id] = allocation_intervals + + # The leave_employees dictionary groups the leavess based on the employee and the holiday type + # The structure is the following: + # - KEYS: + # leave_employees + # |--employee_id + # |--holiday_status_id + # - VALUES: + # Intervals with the start and end date of each leave and associated leave within this interval + leaves_employees = defaultdict(lambda: defaultdict(list)) + leave_intervals = [] + + ### Creation of the leave intervals ### + if leaves: + for holiday_status_id in leaves.holiday_status_id: + for employee_id in employee_ids: + leave_intervals = Intervals([( + fields.datetime.combine(leave.date_from, time.min), + fields.datetime.combine(leave.date_to, time.max), + leave) + for leave in leaves.filtered(lambda leave: leave.employee_id.id == employee_id and leave.holiday_status_id == holiday_status_id)]) + + leaves_employees[employee_id][holiday_status_id] = leave_intervals + + # allocation_days_consumed is a dictionary to map the number of days/hours of leaves taken per allocation + # The structure is the following: + # - KEYS: + # allocation_days_consumed + # |--employee_id + # |--holiday_status_id + # |--allocation + # |--virtual_leaves_taken + # |--leaves_taken + # |--virtual_remaining_leaves + # |--remaining_leaves + # |--max_leaves + # - VALUES: + # Integer representing the number of (virtual) remaining leaves, (virtual) leaves taken or max leaves for each allocation. + # The unit is in hour or days depending on the leave type request unit + allocations_days_consumed = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: 0)))) + + company_domain = [('company_id', 'in', list(set(self.env.company.ids + self.env.context.get('allowed_company_ids', []))))] + + ### Existing leaves assigned to allocations ### + if leaves_employees: + for employee_id, leaves_interval_by_status in leaves_employees.items(): + for holiday_status_id in leaves_interval_by_status: + days_consumed = allocations_days_consumed[employee_id][holiday_status_id] + if allocation_employees[employee_id][holiday_status_id]: + allocations = allocation_employees[employee_id][holiday_status_id] & leaves_interval_by_status[holiday_status_id] + available_allocations = self.env['hr.leave.allocation'] + for allocation_interval in allocations._items: + available_allocations |= allocation_interval[2] + # Consume the allocations that are close to expiration first + sorted_available_allocations = available_allocations.filtered('date_to').sorted(key='date_to') + sorted_available_allocations += available_allocations.filtered(lambda allocation: not allocation.date_to) + leave_intervals = leaves_interval_by_status[holiday_status_id]._items + for leave_interval in leave_intervals: + leave = leave_interval[2] + if leave.leave_type_request_unit in ['day', 'half_day']: + leave_duration = leave.number_of_days + leave_unit = 'days' + else: + leave_duration = leave.number_of_hours_display + leave_unit = 'hours' + for available_allocation in sorted_available_allocations: + virtual_remaining_leaves = (available_allocation.number_of_days if leave_unit == 'days' else available_allocation.number_of_hours_display) - allocations_days_consumed[employee_id][holiday_status_id][available_allocation]['virtual_leaves_taken'] + max_leaves = min(virtual_remaining_leaves, leave_duration) + days_consumed[available_allocation]['virtual_leaves_taken'] += max_leaves + if leave.state == 'validate': + days_consumed[available_allocation]['leaves_taken'] += max_leaves + leave_duration -= max_leaves + if leave_duration > 0: + # There are not enough allocation for the number of leaves + days_consumed[False]['virtual_remaining_leaves'] -= leave_duration + return allocations_days_consumed + + # Future available leaves + for employee_id, allocation_intervals_by_status in allocation_employees.items(): + for holiday_status_id, intervals in allocation_intervals_by_status.items(): + if not intervals: + continue + future_allocation_intervals = intervals & Intervals([( + fields.datetime.combine(date, time.min), + fields.datetime.combine(date, time.max) + timedelta(days=5*365), + self.env['hr.leave'])]) + search_date = date + for future_allocation_interval in future_allocation_intervals._items: + if future_allocation_interval[0].date() > search_date: + continue + for allocation in future_allocation_interval[2]: + days_consumed = allocations_days_consumed[employee_id][holiday_status_id][allocation] + if future_allocation_interval[1] != fields.datetime.combine(date, time.max) + timedelta(days=5*365): + # Compute the remaining number of days/hours in the allocation only if it has an end date + quantity_available = allocation.employee_id._get_work_days_data_batch( + future_allocation_interval[0], + future_allocation_interval[1], + compute_leaves=False, + domain=company_domain)[employee_id] + else: + # If no end date to the allocation, consider the number of days remaining as infinite + quantity_available = {'days': float('inf'), 'hours': float('inf')} + if allocation.type_request_unit in ['day', 'half_day']: + quantity_available = quantity_available['days'] + remaining_days_allocation = (allocation.number_of_days - days_consumed['virtual_leaves_taken']) + else: + quantity_available = quantity_available['hours'] + remaining_days_allocation = (allocation.number_of_hours_display - days_consumed['virtual_leaves_taken']) + if quantity_available <= remaining_days_allocation: + search_date = future_allocation_interval[1].date() + timedelta(days=1) + days_consumed['virtual_remaining_leaves'] += min(quantity_available, remaining_days_allocation) + days_consumed['max_leaves'] = allocation.number_of_days if allocation.type_request_unit == 'day' else allocation.number_of_hours_display + days_consumed['remaining_leaves'] = days_consumed['max_leaves'] - days_consumed['leaves_taken'] + if remaining_days_allocation >= quantity_available: + break + + return allocations_days_consumed + + def get_employees_days(self, employee_ids, date=None): + result = { employee_id: { leave_type.id: { @@ -225,62 +383,16 @@ def get_employees_days(self, employee_ids, date=None): } for employee_id in employee_ids } - requests = self.env['hr.leave'].search([ - ('employee_id', 'in', employee_ids), - ('state', 'in', ['confirm', 'validate1', 'validate']), - ('holiday_status_id', 'in', self.ids) - ]) + allocations_days_consumed = self._get_employees_days_per_allocation(employee_ids, date) - if not date: - date = self.env.context.get('default_date_from') or fields.Date.context_today(self) - allocations = self.env['hr.leave.allocation'].search([ - ('employee_id', 'in', employee_ids), - ('state', 'in', ['confirm', 'validate1', 'validate']), - ('holiday_status_id', 'in', self.ids), - ('date_from', '<=', date), - '|', ('date_to', '=', False), - ('date_to', '>=', date), - ]) + leave_keys = ['max_leaves', 'leaves_taken', 'remaining_leaves', 'virtual_remaining_leaves', 'virtual_leaves_taken'] + + for employee_id in allocations_days_consumed: + for holiday_status_id in allocations_days_consumed[employee_id]: + for allocation in allocations_days_consumed[employee_id][holiday_status_id]: + for leave_key in leave_keys: + result[employee_id][holiday_status_id if isinstance(holiday_status_id, int) else holiday_status_id.id][leave_key] += allocations_days_consumed[employee_id][holiday_status_id][allocation][leave_key] - for request in requests: - status_dict = result[request.employee_id.id][request.holiday_status_id.id] - if not request.holiday_allocation_id or request.holiday_allocation_id in allocations: - status_dict['virtual_remaining_leaves'] -= (request.number_of_hours_display - if request.leave_type_request_unit == 'hour' - else request.number_of_days) - if request.holiday_status_id.requires_allocation == 'no': - status_dict['virtual_leaves_taken'] += (request.number_of_hours_display - if request.leave_type_request_unit == 'hour' - else request.number_of_days) - if request.state == 'validate': - status_dict['leaves_taken'] += (request.number_of_hours_display - if request.leave_type_request_unit == 'hour' - else request.number_of_days) - status_dict['remaining_leaves'] -= (request.number_of_hours_display - if request.leave_type_request_unit == 'hour' - else request.number_of_days) - - for allocation in allocations.sudo(): - status_dict = result[allocation.employee_id.id][allocation.holiday_status_id.id] - if allocation.state == 'validate': - status_dict['virtual_remaining_leaves'] += (allocation.number_of_hours_display - if allocation.type_request_unit == 'hour' - else allocation.number_of_days) - if allocation.holiday_status_id.requires_allocation == 'no': - # 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['max_leaves'] += (allocation.number_of_hours_display - if allocation.type_request_unit == 'hour' - else allocation.number_of_days) - status_dict['remaining_leaves'] += (allocation.number_of_hours_display - if allocation.type_request_unit == 'hour' - else allocation.number_of_days) - else: - remaining_leaves = allocation.max_leaves - allocation.leaves_taken - status_dict['max_leaves'] += allocation.max_leaves - status_dict['remaining_leaves'] += remaining_leaves - status_dict['leaves_taken'] += allocation.leaves_taken return result @api.model diff --git a/addons/hr_holidays/tests/test_company_leave.py b/addons/hr_holidays/tests/test_company_leave.py index fcc3f832d2eaf..ffd7b008be310 100644 --- a/addons/hr_holidays/tests/test_company_leave.py +++ b/addons/hr_holidays/tests/test_company_leave.py @@ -317,7 +317,7 @@ def test_leave_whole_company_07(self): }) company_leave._compute_date_from_to() - with self.assertQueryCount(__system__=773, admin=867): # 770 community + with self.assertQueryCount(__system__=774, admin=867): # 770 community # Original query count: 1987 # Without tracking/activity context keys: 5154 company_leave.action_validate() diff --git a/addons/hr_holidays/tests/test_leave_requests.py b/addons/hr_holidays/tests/test_leave_requests.py index 17f1bc62ca985..8ce8bbfd9b863 100644 --- a/addons/hr_holidays/tests/test_leave_requests.py +++ b/addons/hr_holidays/tests/test_leave_requests.py @@ -90,17 +90,9 @@ def test_overlapping_requests(self): @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') def test_limited_type_no_days(self): - """ Employee creates a leave request in a limited category but has not enough days left """ - - with self.assertRaises(ValidationError): - self.env['hr.leave'].with_user(self.user_employee_id).create({ - 'name': 'Hol22', - 'employee_id': self.employee_emp_id, - 'holiday_status_id': self.holidays_type_2.id, - 'date_from': (datetime.today() + relativedelta(days=1)).strftime('%Y-%m-%d %H:%M'), - 'date_to': (datetime.today() + relativedelta(days=2)), - 'number_of_days': 1, - }) + # Deprecated as part of https://github.com/odoo/odoo/pull/96545 + # TODO: remove in master + return @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') def test_limited_type_days_left(self): @@ -162,16 +154,9 @@ def test_accrual_validity_time_valid(self): @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') def test_accrual_validity_time_not_valid(self): - """ Employee ask leave when there's no valid allocation """ - with self.assertRaises(ValidationError): - self.env['hr.leave'].with_user(self.user_employee).create({ - 'name': 'Sick Time Off', - 'employee_id': self.employee_emp_id, - 'holiday_status_id': self.holidays_type_2.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'), - 'number_of_days': 1, - }) + # Deprecated as part of https://github.com/odoo/odoo/pull/96545 + # TODO: remove in master + return @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') def test_department_leave(self): @@ -605,23 +590,8 @@ def test_several_allocations(self): allocation1.action_validate() allocation2.action_validate() - # Neither allocation has enough days - with self.assertRaises(ValidationError): - self.env['hr.leave'].with_user(self.user_employee_id).create({ - 'name': 'Holiday Request', - 'employee_id': self.employee_emp_id, - 'holiday_status_id': self.holidays_type_2.id, - 'date_from': '2022-01-01', - 'date_to': '2022-01-15', - 'number_of_days': 10, - }) - - allocation_vals.update({'number_of_days': 10}) - allocation3 = self.env['hr.leave.allocation'].create(allocation_vals) - allocation3.action_validate() - - # The 3rd allocation has enough days, so it should be picked - holiday = self.env['hr.leave'].with_user(self.user_employee_id).create({ + # Able to create a leave of 10 days with two allocations of 5 days + self.env['hr.leave'].with_user(self.user_employee_id).create({ 'name': 'Holiday Request', 'employee_id': self.employee_emp_id, 'holiday_status_id': self.holidays_type_2.id, @@ -629,11 +599,6 @@ def test_several_allocations(self): 'date_to': '2022-01-15', 'number_of_days': 10, }) - holiday.sudo().action_validate() - - self.assertEqual(allocation1.leaves_taken, 0.0, 'As this allocation does not have enough days, it should not be affected') - self.assertEqual(allocation2.leaves_taken, 0.0, 'As this allocation does not have enough days, it should not be affected') - self.assertEqual(allocation3.leaves_taken, 10.0, 'As this allocation has enough days, the leave days should be taken') def test_several_allocations_split(self): Allocation = self.env['hr.leave.allocation'] @@ -684,7 +649,9 @@ def test_several_allocations_split(self): leaves = (leave_4days + leave_1day) leaves.action_approve() - self.assertEqual(allocation_4days.leaves_taken, leave_4days['number_of_%ss_display' % unit], 'As 4 days were available in this allocation, they should have been taken') - self.assertEqual(allocation_1day.leaves_taken, leave_1day['number_of_%ss_display' % unit], 'As no days were available in previous allocation, they should have been taken in this one') + allocation_days = self.holidays_type_2._get_employees_days_per_allocation([self.employee_emp_id]) + + self.assertEqual(allocation_days[self.employee_emp_id][self.holidays_type_2][allocation_4days]['leaves_taken'], leave_4days['number_of_%ss_display' % unit], 'As 4 days were available in this allocation, they should have been taken') + self.assertEqual(allocation_days[self.employee_emp_id][self.holidays_type_2][allocation_1day]['leaves_taken'], leave_1day['number_of_%ss_display' % unit], 'As no days were available in previous allocation, they should have been taken in this one') leaves.action_refuse() allocations.action_refuse() diff --git a/addons/hr_holidays/views/hr_leave_allocation_views.xml b/addons/hr_holidays/views/hr_leave_allocation_views.xml index c9449cb20cfe3..bc12f8e0fb7e8 100644 --- a/addons/hr_holidays/views/hr_leave_allocation_views.xml +++ b/addons/hr_holidays/views/hr_leave_allocation_views.xml @@ -71,7 +71,7 @@ class="oe_stat_button" icon="fa-calendar" type="action" - attrs="{'invisible': ['|', '|', ('id', '=', False), ('holiday_type', '!=', 'employee'), ('employee_id', '=', False)]}" + invisible="1" name="%(hr_leave_action_holiday_allocation_id)d" help="Time off Taken/Total Allocated">
diff --git a/addons/hr_work_entry_holidays/tests/test_performance.py b/addons/hr_work_entry_holidays/tests/test_performance.py index 68bddab55ef76..36d3e69e3e273 100644 --- a/addons/hr_work_entry_holidays/tests/test_performance.py +++ b/addons/hr_work_entry_holidays/tests/test_performance.py @@ -31,7 +31,7 @@ def test_performance_leave_validate(self): self.richard_emp.generate_work_entries(date(2018, 1, 1), date(2018, 1, 2)) leave = self.create_leave(datetime(2018, 1, 1, 7, 0), datetime(2018, 1, 1, 18, 0)) - with self.assertQueryCount(__system__=92, admin=93): + with self.assertQueryCount(__system__=94, admin=95): leave.action_validate() leave.action_refuse() @@ -40,14 +40,14 @@ def test_performance_leave_validate(self): def test_performance_leave_write(self): leave = self.create_leave(datetime(2018, 1, 1, 7, 0), datetime(2018, 1, 1, 18, 0)) - with self.assertQueryCount(__system__=19, admin=19): + with self.assertQueryCount(__system__=21, admin=30): leave.date_to = datetime(2018, 1, 1, 19, 0) leave.action_refuse() @users('__system__', 'admin') @warmup def test_performance_leave_create(self): - with self.assertQueryCount(__system__=26, admin=27): + with self.assertQueryCount(__system__=27, admin=28): leave = self.create_leave(datetime(2018, 1, 1, 7, 0), datetime(2018, 1, 1, 18, 0)) leave.action_refuse() @@ -56,7 +56,7 @@ def test_performance_leave_create(self): def test_performance_leave_confirm(self): leave = self.create_leave(datetime(2018, 1, 1, 7, 0), datetime(2018, 1, 1, 18, 0)) leave.action_draft() - with self.assertQueryCount(__system__=18, admin=19): + with self.assertQueryCount(__system__=22, admin=23): leave.action_confirm() leave.state = 'refuse'