[FIX] hr_holidays: fix nextcall on create

To reproduce the bug:
- create an accrual allocation with the seniority plan
- set the start date way in the past like in 2000
- validate the allocation
- go on the dashboard, the accrued amount should be broken
when setting the balance on a future date
- additional days accrued if the cron is run

Fix:
nextcall being unset upon creation by default, the allocation
would consider the start of the second level as the nextcall if
the allocation is created in the past. This commits sets nextcall
to a correct value if the lastcall is set in the past upon creation.

closes odoo/odoo#141006

Signed-off-by: Bertrand Dossogne (bedo) <bedo@odoo.com>
This commit is contained in:
Dossogne Bertrand
2023-11-21 09:21:13 +00:00
parent 58cd2cbfd0
commit 1e27f665d4
3 changed files with 86 additions and 9 deletions
@@ -609,17 +609,26 @@ class HolidaysAllocation(models.Model):
def _add_lastcalls(self):
for allocation in self:
if allocation.allocation_type != 'accrual' or allocation.lastcall:
if allocation.allocation_type != 'accrual':
continue
today = fields.Date.today()
current_level = allocation._get_current_accrual_plan_level_id(today)[0]
if not current_level:
allocation.lastcall = today
continue
allocation.lastcall = max(
current_level._get_previous_date(today),
allocation.date_from + get_timedelta(current_level.start_count, current_level.start_type)
)
(current_level, current_level_idx) = allocation._get_current_accrual_plan_level_id(today)
if not allocation.lastcall:
if not current_level:
allocation.lastcall = today
continue
allocation.lastcall = max(
current_level._get_previous_date(today),
allocation.date_from + get_timedelta(current_level.start_count, current_level.start_type)
)
if not allocation.nextcall and allocation.lastcall < today:
accrual_plan = allocation.accrual_plan_id
next_level = False
allocation.nextcall = current_level._get_next_date(allocation.lastcall)
if current_level_idx < (len(accrual_plan.level_ids) - 1) and accrual_plan.transition_mode == 'immediately':
next_level = allocation.accrual_plan_id.level_ids[current_level_idx + 1]
next_level_start = allocation.date_from + get_timedelta(next_level.start_count, next_level.start_type)
allocation.nextcall = min(allocation.nextcall, next_level_start)
def add_follower(self, employee_id):
employee = self.env['hr.employee'].browse(employee_id)
+1
View File
@@ -19,3 +19,4 @@ from . import test_global_leaves
from . import test_uninstall
from . import test_holidays_calendar
from . import test_negative
from . import test_past_accruals
@@ -0,0 +1,67 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date
from freezegun import freeze_time
from odoo.tests import tagged
from odoo.addons.hr_holidays.tests.common import TestHrHolidaysCommon
@tagged('post_install', '-at_install', 'accruals')
class TestAccrualAllocations(TestHrHolidaysCommon):
@classmethod
def setUpClass(cls):
super(TestAccrualAllocations, cls).setUpClass()
cls.leave_type = cls.env['hr.leave.type'].create({
'name': 'Accrual Time Off',
'time_type': 'leave',
'requires_allocation': 'yes',
'allocation_validation_type': 'no',
})
cls.accrual_plan = cls.env['hr.leave.accrual.plan'].with_context(tracking_disable=True).create({
'name': 'Test Seniority Plan',
'level_ids': [
(0, 0, {
'start_count': 1,
'start_type': 'day',
'added_value': 1,
'added_value_type': 'day',
'frequency': 'yearly',
'cap_accrued_time': True,
'maximum_leave': 10000,
}),
(0, 0, {
'start_count': 4,
'start_type': 'year',
'added_value': 1,
'added_value_type': 'day',
'frequency': 'yearly',
'cap_accrued_time': True,
'maximum_leave': 10000,
}),
(0, 0, {
'start_count': 8,
'start_type': 'year',
'added_value': 1,
'added_value_type': 'day',
'frequency': 'yearly',
'cap_accrued_time': True,
'maximum_leave': 10000,
}),
]
})
def _test_past_accrual(self):
with freeze_time("2023-12-01"):
allocation = self.env['hr.leave.allocation'].create({
'employee_id': self.employee_emp_id,
'allocation_type': 'accrual',
'accrual_plan_id': self.accrual_plan.id,
'holiday_status_id': self.leave_type.id,
'date_from': date(2000, 1, 1),
'number_of_days': 0,
})
allocation._process_accrual_plans()
self.assertEqual(allocation.number_of_days, 0)