[IMP] hr_holidays: improve days calculation based on worked time
Prior to this commit accrual levels based on worked time did not properly compute the number of days when the period prorata was taken into account. TaskId-2924364 closes odoo/odoo#99183 X-original-commit: d9000d3d883ab6fa8325692f1ac5249d6822046a Signed-off-by: William Braeckman (wbr) <wbr@odoo.com>
This commit is contained in:
@@ -379,12 +379,19 @@ class HolidaysAllocation(models.Model):
|
||||
self.ensure_one()
|
||||
if level.is_based_on_worked_time:
|
||||
start_dt = datetime.combine(start_date, datetime.min.time())
|
||||
end_dt = datetime.combine(end_date, datetime.max.time())
|
||||
end_dt = datetime.combine(end_date, datetime.min.time())
|
||||
worked = self.employee_id._get_work_days_data_batch(start_dt, end_dt, calendar=self.employee_id.resource_calendar_id)\
|
||||
[self.employee_id.id]['hours']
|
||||
if start_period != start_date or end_period != end_date:
|
||||
start_dt = datetime.combine(start_period, datetime.min.time())
|
||||
end_dt = datetime.combine(end_period, datetime.min.time())
|
||||
planned_worked = self.employee_id._get_work_days_data_batch(start_dt, end_dt, calendar=self.employee_id.resource_calendar_id)\
|
||||
[self.employee_id.id]['hours']
|
||||
else:
|
||||
planned_worked = worked
|
||||
left = self.employee_id.sudo()._get_leave_days_data_batch(start_dt, end_dt,
|
||||
domain=[('time_type', '=', 'leave')])[self.employee_id.id]['hours']
|
||||
work_entry_prorata = worked / (left + worked) if worked else 0
|
||||
work_entry_prorata = worked / (left + planned_worked) if (left + planned_worked) else 0
|
||||
added_value = work_entry_prorata * level.added_value
|
||||
else:
|
||||
added_value = level.added_value
|
||||
@@ -392,7 +399,7 @@ class HolidaysAllocation(models.Model):
|
||||
if level.added_value_type == 'hours':
|
||||
added_value = added_value / (self.employee_id.sudo().resource_id.calendar_id.hours_per_day or HOURS_PER_DAY)
|
||||
period_prorata = 1
|
||||
if start_period != start_date or end_period != end_date:
|
||||
if (start_period != start_date or end_period != end_date) and not level.is_based_on_worked_time:
|
||||
period_days = (end_period - start_period)
|
||||
call_days = (end_date - start_date)
|
||||
period_prorata = min(1, call_days / period_days) if period_days else 1
|
||||
|
||||
@@ -285,24 +285,26 @@ class TestAccrualAllocations(TestHrHolidaysCommon):
|
||||
# 2 accruals, one based on worked time, one not
|
||||
# check gain
|
||||
with freeze_time('2021-08-30'):
|
||||
attendances = []
|
||||
for index in range(5):
|
||||
attendances.append((0, 0, {
|
||||
'name': '%s_%d' % ('40 Hours', index),
|
||||
'hour_from': 8,
|
||||
'hour_to': 12,
|
||||
'dayofweek': str(index),
|
||||
'day_period': 'morning'
|
||||
}))
|
||||
attendances.append((0, 0, {
|
||||
'name': '%s_%d' % ('40 Hours', index),
|
||||
'hour_from': 13,
|
||||
'hour_to': 17,
|
||||
'dayofweek': str(index),
|
||||
'day_period': 'afternoon'
|
||||
}))
|
||||
calendar_emp = self.env['resource.calendar'].create({
|
||||
'name': '40 Hours',
|
||||
'tz': self.employee_emp.tz,
|
||||
'attendance_ids': [
|
||||
(0, 0, {
|
||||
'name': '%s_%d' % ('40 Hours', index),
|
||||
'hour_from': 8,
|
||||
'hour_to': 12,
|
||||
'dayofweek': str(index),
|
||||
'day_period': 'morning'
|
||||
}, {
|
||||
'name': '%s_%d' % ('40 Hours', index),
|
||||
'hour_from': 13,
|
||||
'hour_to': 18,
|
||||
'dayofweek': str(index),
|
||||
'day_period': 'afternoon'
|
||||
}) for index in range(5)
|
||||
],
|
||||
'attendance_ids': attendances,
|
||||
})
|
||||
self.employee_emp.resource_calendar_id = calendar_emp.id
|
||||
|
||||
@@ -377,7 +379,7 @@ class TestAccrualAllocations(TestHrHolidaysCommon):
|
||||
# 3.75 -> starts 1 day after allocation date -> 31/08-3/09 => 4 days - 1 days time off => (3 / 4) * 5 days
|
||||
# ^ result without prorata
|
||||
# Prorated
|
||||
self.assertAlmostEqual(allocation_worked_time.number_of_days, 3.42857, 4, 'There should be 3.42857 days allocated.')
|
||||
self.assertAlmostEqual(allocation_worked_time.number_of_days, 3, 4, 'There should be 3 days allocated.')
|
||||
self.assertEqual(allocation_not_worked_time.nextcall, datetime.date(2021, 9, 13), 'The next call date of the cron should be the September 13th')
|
||||
self.assertEqual(allocation_worked_time.nextcall, datetime.date(2021, 9, 13), 'The next call date of the cron should be the September 13th')
|
||||
|
||||
@@ -386,7 +388,7 @@ class TestAccrualAllocations(TestHrHolidaysCommon):
|
||||
self.env['hr.leave.allocation']._update_accrual()
|
||||
self.assertAlmostEqual(allocation_not_worked_time.number_of_days, 9.2857, 4, 'There should be 9.2857 days allocated.')
|
||||
self.assertEqual(allocation_not_worked_time.nextcall, next_date, 'The next call date of the cron should be September 20th')
|
||||
self.assertAlmostEqual(allocation_worked_time.number_of_days, 8.42857, 4, 'There should be 8.42857 days allocated.')
|
||||
self.assertAlmostEqual(allocation_worked_time.number_of_days, 8, 4, 'There should be 8 days allocated.')
|
||||
self.assertEqual(allocation_worked_time.nextcall, next_date, 'The next call date of the cron should be September 20th')
|
||||
|
||||
def test_check_max_value(self):
|
||||
|
||||
Reference in New Issue
Block a user