[FIX] hr_holidays: negative allocation in accural plan

Steps to reproduce:

- Create an accural plan with two levels, the first should have
its action_with_unused_accruals set as lost. The second should
start one year after the first level.
- Use this plan on a employee and make it start the first day of
the previous year.

Current behavior:
The number of allocated day is wrong and can even be negative

Expected behavior:
The days of the first level are lost and there is the right amount
of allocated days,

Eplanation:
The _end_of_the_year function was first designed to be only called
on the first day of the year but the it changed since then without
updating it's content and it can calle any day of the year now. In
this case the use of today() does not make sense and it should be
replaced by the first day of the current year.

opw-2868297

closes odoo/odoo#94897

X-original-commit: 476818972e93b32df6f25cf299f631a8f7eb3af4
Signed-off-by: Fockedey Martin (mafo) <mafo@odoo.com>
Signed-off-by: Kevin Baptiste <kba@odoo.com>
This commit is contained in:
mafo-odoo
2022-06-30 08:23:02 +02:00
parent 8566928015
commit 92ef335bee
2 changed files with 46 additions and 4 deletions
@@ -331,21 +331,22 @@ class HolidaysAllocation(models.Model):
# to override in payroll
today = fields.Date.today()
last_day_last_year = today + relativedelta(years=-1, month=12, day=31)
first_day_this_year = today + relativedelta(month=1, day=1)
for allocation in self:
current_level = allocation._get_current_accrual_plan_level_id(today)[0]
current_level = allocation._get_current_accrual_plan_level_id(first_day_this_year)[0]
if not current_level:
continue
nextcall = current_level._get_next_date(today)
nextcall = current_level._get_next_date(first_day_this_year)
if current_level.action_with_unused_accruals == 'lost':
# Allocations are lost but number_of_days should not be lower than leaves_taken
allocation.write({'number_of_days': allocation.leaves_taken, 'lastcall': today, 'nextcall': nextcall})
allocation.write({'number_of_days': allocation.leaves_taken, 'lastcall': first_day_this_year, 'nextcall': nextcall})
elif current_level.action_with_unused_accruals == 'postponed' and current_level.postpone_max_days:
# Make sure the period was ran until the last day of last year
if allocation.nextcall:
allocation.nextcall = last_day_last_year
allocation._process_accrual_plans(last_day_last_year, True)
number_of_days = min(allocation.number_of_days - allocation.leaves_taken, current_level.postpone_max_days) + allocation.leaves_taken
allocation.write({'number_of_days': number_of_days, 'lastcall': today, 'nextcall': nextcall})
allocation.write({'number_of_days': number_of_days, 'lastcall': first_day_this_year, 'nextcall': nextcall})
def _get_current_accrual_plan_level_id(self, date, level_ids=False):
"""
@@ -641,6 +641,47 @@ class TestAccrualAllocations(TestHrHolidaysCommon):
allocation._update_accrual()
self.assertAlmostEqual(allocation.number_of_days, 30.79, 2, "Invalid number of days")
def test_accrual_lost_previous_days(self):
# Test that when an allocation with two levels is made and that the first level has it's action
# with unused accruals set as lost that the days are effectively lost
accrual_plan = self.env['hr.leave.accrual.plan'].with_context(tracking_disable=True).create({
'name': 'Accrual Plan For Test',
'level_ids': [
(0, 0, {
'start_count': 0,
'start_type': 'day',
'added_value': 1,
'added_value_type': 'days',
'frequency': 'monthly',
'maximum_leave': 12,
'action_with_unused_accruals': 'lost',
}),
(0, 0, {
'start_count': 1,
'start_type': 'year',
'added_value': 1,
'added_value_type': 'days',
'frequency': 'monthly',
'maximum_leave': 12,
'action_with_unused_accruals': 'lost',
}),
],
})
allocation = self.env['hr.leave.allocation'].with_user(self.user_hrmanager_id).with_context(tracking_disable=True).create({
'name': 'Accrual Allocation - Test',
'accrual_plan_id': accrual_plan.id,
'employee_id': self.employee_emp.id,
'holiday_status_id': self.leave_type.id,
'number_of_days': 0,
'allocation_type': 'accrual',
'date_from': datetime.date(2021, 1, 1),
})
allocation.action_confirm()
allocation.action_validate()
with freeze_time('2022-4-4'):
allocation._update_accrual()
self.assertEqual(allocation.number_of_days, 3, "Invalid number of days")
def test_accrual_maximum_leaves(self):
accrual_plan = self.env['hr.leave.accrual.plan'].with_context(tracking_disable=True).create({
'name': 'Accrual Plan For Test',