diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py index e80a29357b6..47e1fd16654 100644 --- a/addons/hr_holidays/models/hr_leave_type.py +++ b/addons/hr_holidays/models/hr_leave_type.py @@ -326,17 +326,22 @@ class HolidaysType(models.Model): 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 holiday_status_id.requires_allocation != 'no': + 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 + else: + days_consumed[False]['virtual_leaves_taken'] += leave_duration 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 + days_consumed[False]['leaves_taken'] += leave_duration # Future available leaves for employee_id, allocation_intervals_by_status in allocation_employees.items(): diff --git a/addons/hr_holidays/tests/test_leave_requests.py b/addons/hr_holidays/tests/test_leave_requests.py index f39e15d75a6..248d43ed073 100644 --- a/addons/hr_holidays/tests/test_leave_requests.py +++ b/addons/hr_holidays/tests/test_leave_requests.py @@ -767,3 +767,79 @@ class TestLeaveRequests(TestHrHolidaysCommon): 'date_to': '2021-11-19 23:59:59', }) self.assertEqual(time_off.active, False) + def test_holiday_type_requires_no_allocation(self): + # holiday_type_2 initially requires an allocation + # Once an allocation is granted and a leave is taken, + # the holiday type is changed to no longer require an allocation. + # Leaves taken and available days should be correctly computed. + with freeze_time('2020-09-15'): + allocation = self.env['hr.leave.allocation'].create({ + 'name': 'Expired Allocation', + 'employee_id': self.employee_emp_id, + 'holiday_status_id': self.holidays_type_2.id, + 'number_of_days': 5, + 'state': 'confirm', + 'date_from': '2020-01-01', + 'date_to': '2020-12-31', + }) + allocation.action_validate() + leave1 = 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': '2020-09-06', + 'date_to': '2020-09-08', + 'number_of_days': 3, + }) + + self.assertEqual( + self.holidays_type_2.get_employees_days([self.employee_emp_id])[self.employee_emp_id][self.holidays_type_2.id], + { + 'closest_allocation_to_expire': allocation, + 'max_leaves': 5, + 'leaves_taken': 0, + 'remaining_leaves': 5, + 'virtual_remaining_leaves': 2, + 'virtual_leaves_taken': 3, + } + ) + + self.holidays_type_2.requires_allocation = 'no' + leave2 = 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': '2020-07-06', + 'date_to': '2020-07-08', + 'number_of_days': 3, + }) + + # The 5 allocation days are not consumed anymore + # virtual_remaining_leaves reflect the total number of leave days taken + self.assertEqual( + self.holidays_type_2.get_employees_days([self.employee_emp_id])[self.employee_emp_id][self.holidays_type_2.id], + { + 'closest_allocation_to_expire': allocation, + 'max_leaves': 5, + 'leaves_taken': 0, + 'remaining_leaves': 5, + 'virtual_remaining_leaves': 5, + 'virtual_leaves_taken': 6, + } + ) + + leave1.with_user(self.user_hrmanager_id).action_approve() + leave2.with_user(self.user_hrmanager_id).action_approve() + + # leaves_taken and virtual_leaves_taken reflect the total number of leave days taken + self.assertEqual( + self.holidays_type_2.get_employees_days([self.employee_emp_id])[self.employee_emp_id][self.holidays_type_2.id], + { + 'closest_allocation_to_expire': allocation, + 'max_leaves': 5, + 'leaves_taken': 6, + 'remaining_leaves': 5, + 'virtual_remaining_leaves': 5, + 'virtual_leaves_taken': 6, + } + )