[FIX] hr_holidays: remove allocation_id on hr.leave

As part of hr_holidays B2B, the holidays allowances were moved from hr_leave_type to hr_leave_allocation.
This didn't allow to take a leave longer than the maximum duration of an allocation. Also, despite all the
allocations could have enough days for a certain leave, it was not possible to use all available days without
splitting the leaves across the different allocations.

This commit moves the holidays allowance to the hr_leave_type to remediate the issues described above.

task-2834887

closes odoo/odoo#98317

X-original-commit: 8c37d5c7cc397e517c43c1ec13a131b4b35e48b7
Signed-off-by: phwa-odoo <phwa@odoo.com>
This commit is contained in:
Philippe Wauthy
2022-08-18 00:23:40 +02:00
parent 992dfc4312
commit d57aba65fa
7 changed files with 212 additions and 202 deletions
+15 -85
View File
@@ -315,9 +315,9 @@ class HolidaysRequest(models.Model):
@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):
@@ -356,49 +356,9 @@ class HolidaysRequest(models.Model):
@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', 'employee_id')
@@ -735,13 +695,13 @@ class HolidaysRequest(models.Model):
@api.constrains('state', 'number_of_days', 'holiday_status_id')
def _check_holidays(self):
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':
mapped_days = self.holiday_status_id.get_employees_days(holiday.employee_id.ids, holiday.date_from.date())
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):
@@ -886,43 +846,15 @@ class HolidaysRequest(models.Model):
@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
@api.constrains('date_from', 'date_to')
def _check_stress_day(self):
@@ -1003,8 +935,6 @@ class HolidaysRequest(models.Model):
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
@@ -194,11 +194,10 @@ class HolidaysAllocation(models.Model):
@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):
+178 -64
View File
@@ -7,12 +7,14 @@ import datetime
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 import format_date
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__)
@@ -220,7 +222,170 @@ class HolidaysType(models.Model):
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
# |--closest_allocation_to_expire
# - 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)
allocations_days_consumed[employee_id][holiday_status_id][False]['closest_allocation_to_expire'] = sorted_available_allocations[0] if sorted_available_allocations else False
leave_intervals = leaves_interval_by_status[holiday_status_id]._items
for leave_interval in leave_intervals:
leaves = leave_interval[2]
for leave in leaves:
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
allocations_of_that_type = intervals._items[0][2].filtered(lambda a: a.date_to and a.state == 'validate' and a.date_to >= date)
allocations_sorted = sorted(allocations_of_that_type, key=lambda a: a.date_to)
allocation_closest = allocations_sorted[0] if allocations_sorted else False
allocations_days_consumed[employee_id][holiday_status_id][False]['closest_allocation_to_expire'] = allocation_closest
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: {
@@ -234,72 +399,21 @@ class HolidaysType(models.Model):
} 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 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)
allocation_closest_by_type = {}
for holiday_status_id in self.ids:
allocations_of_that_type = allocations.filtered(lambda a: a.holiday_status_id.id == holiday_status_id and a.date_to and a.state == 'validate')
allocations_sorted = sorted(allocations_of_that_type, key=lambda a: a.date_to)
allocation_closest = allocations_sorted[0] if allocations_sorted else False
allocation_closest_by_type[holiday_status_id] = {
'closest_allocation_to_expire': allocation_closest,
}
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
status_dict['closest_allocation_to_expire'] = allocation_closest_by_type[allocation.holiday_status_id.id]['closest_allocation_to_expire']
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]:
if allocation:
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]
else:
result[employee_id][holiday_status_id if isinstance(holiday_status_id, int) else holiday_status_id.id]['closest_allocation_to_expire'] = allocations_days_consumed[employee_id][holiday_status_id][False]['closest_allocation_to_expire']
for leave_key in leave_keys:
if allocations_days_consumed[employee_id][holiday_status_id][False].get(leave_key):
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][False][leave_key]
return result
@api.model
@@ -323,7 +323,7 @@ class TestCompanyLeave(TransactionCase):
})
company_leave._compute_date_from_to()
with self.assertQueryCount(__system__=350, admin=865):
with self.assertQueryCount(__system__=774, admin=867): # 770 community
# Original query count: 1987
# Without tracking/activity context keys: 5154
company_leave.action_validate()
+12 -45
View File
@@ -92,17 +92,9 @@ class TestLeaveRequests(TestHrHolidaysCommon):
@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):
@@ -164,16 +156,9 @@ class TestLeaveRequests(TestHrHolidaysCommon):
@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):
@@ -619,23 +604,8 @@ class TestLeaveRequests(TestHrHolidaysCommon):
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,
@@ -643,11 +613,6 @@ class TestLeaveRequests(TestHrHolidaysCommon):
'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']
@@ -698,8 +663,10 @@ class TestLeaveRequests(TestHrHolidaysCommon):
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()
@@ -78,7 +78,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">
<div class="o_stat_info">
@@ -31,7 +31,7 @@ class TestWorkEntryHolidaysPerformance(TestWorkEntryHolidaysBase):
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__=90, admin=91):
with self.assertQueryCount(__system__=93, admin=94):
leave.action_validate()
leave.action_refuse()
@@ -40,7 +40,7 @@ class TestWorkEntryHolidaysPerformance(TestWorkEntryHolidaysBase):
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__=18, admin=18):
with self.assertQueryCount(__system__=21, admin=30):
leave.date_to = datetime(2018, 1, 1, 19, 0)
leave.action_refuse()
@@ -56,7 +56,7 @@ class TestWorkEntryHolidaysPerformance(TestWorkEntryHolidaysBase):
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__=19, admin=20): # 18/19 com
with self.assertQueryCount(__system__=23, admin=24):
leave.action_confirm()
leave.state = 'refuse'