[FIX] hr_holidays: Automatically set leave dates with 2 week calendar
Commit c7f11aa fixed computation leave length but
forgot to adapt the code when a 2 week calendar is used.
This leads to a traceback when creating a leave for an employee
with a 2 week calendar.
This commit rectifies this.
closes odoo/odoo#37566
Signed-off-by: Romain Libert (rli) <rli@odoo.com>
This commit is contained in:
@@ -22,7 +22,7 @@ _logger = logging.getLogger(__name__)
|
||||
|
||||
# Used to agglomerate the attendances in order to find the hour_from and hour_to
|
||||
# See _onchange_request_parameters
|
||||
DummyAttendance = namedtuple('DummyAttendance', 'hour_from, hour_to, dayofweek, day_period')
|
||||
DummyAttendance = namedtuple('DummyAttendance', 'hour_from, hour_to, dayofweek, day_period, week_type')
|
||||
|
||||
class HolidaysRequest(models.Model):
|
||||
""" Leave Requests Access specifications
|
||||
@@ -284,29 +284,29 @@ class HolidaysRequest(models.Model):
|
||||
|
||||
resource_calendar_id = self.employee_id.resource_calendar_id or self.env.company.resource_calendar_id
|
||||
domain = [('calendar_id', '=', resource_calendar_id.id), ('display_type', '=', False)]
|
||||
attendances = self.env['resource.calendar.attendance'].read_group(domain, ['ids:array_agg(id)', 'hour_from:min(hour_from)', 'hour_to:max(hour_to)', 'dayofweek', 'day_period'], ['dayofweek', 'day_period'], lazy=False)
|
||||
attendances = self.env['resource.calendar.attendance'].read_group(domain, ['ids:array_agg(id)', 'hour_from:min(hour_from)', 'hour_to:max(hour_to)', 'week_type', 'dayofweek', 'day_period'], ['week_type', 'dayofweek', 'day_period'], lazy=False)
|
||||
|
||||
# Must be sorted by dayofweek ASC and day_period DESC
|
||||
attendances = sorted([DummyAttendance(group['hour_from'], group['hour_to'], group['dayofweek'], group['day_period']) for group in attendances], key=lambda att: (att.dayofweek, att.day_period != 'morning'))
|
||||
attendances = sorted([DummyAttendance(group['hour_from'], group['hour_to'], group['dayofweek'], group['day_period'], group['week_type']) for group in attendances], key=lambda att: (att.dayofweek, att.day_period != 'morning'))
|
||||
|
||||
default_value = DummyAttendance(0, 0, 0, 'morning')
|
||||
default_value = DummyAttendance(0, 0, 0, 'morning', False)
|
||||
|
||||
if resource_calendar_id.two_weeks_calendar:
|
||||
# find week type of start_date
|
||||
start_week_type = int(math.floor((self.request_date_from.toordinal() - 1) / 7) % 2)
|
||||
attendance_actual_week = attendances.filtered(lambda att: att.week_type is False or int(att.week_type) == start_week_type)
|
||||
attendance_actual_next_week = attendances.filtered(lambda att: att.week_type is False or int(att.week_type) != start_week_type)
|
||||
attendance_actual_week = [att for att in attendances if att.week_type is False or int(att.week_type) == start_week_type]
|
||||
attendance_actual_next_week = [att for att in attendances if att.week_type is False or int(att.week_type) != start_week_type]
|
||||
# First, add days of actual week coming after date_from
|
||||
attendance_filtred = list(attendance_actual_week.filtered(lambda att: int(att.dayofweek) >= self.request_date_from.weekday()))
|
||||
attendance_filtred = [att for att in attendance_actual_week if int(att.dayofweek) >= self.request_date_from.weekday()]
|
||||
# Second, add days of the other type of week
|
||||
attendance_filtred += list(attendance_actual_next_week)
|
||||
# Third, add days of actual week (to consider days that we have remove first because they coming before date_from)
|
||||
attendance_filtred += list(attendance_actual_week)
|
||||
|
||||
end_week_type = int(math.floor((self.request_date_to.toordinal() - 1) / 7) % 2)
|
||||
attendance_actual_week = attendances.filtered(lambda att: att.week_type is False or int(att.week_type) == end_week_type)
|
||||
attendance_actual_next_week = attendances.filtered(lambda att: att.week_type is False or int(att.week_type) != end_week_type)
|
||||
attendance_filtred_reversed = list(reversed(attendance_actual_week.filtered(lambda att: int(att.dayofweek) <= self.request_date_to.weekday())))
|
||||
attendance_actual_week = [att for att in attendances if att.week_type is False or int(att.week_type) == end_week_type]
|
||||
attendance_actual_next_week = [att for att in attendances if att.week_type is False or int(att.week_type) != end_week_type]
|
||||
attendance_filtred_reversed = list(reversed([att for att in attendance_actual_week if int(att.dayofweek) <= self.request_date_to.weekday()]))
|
||||
attendance_filtred_reversed += list(reversed(attendance_actual_next_week))
|
||||
attendance_filtred_reversed += list(reversed(attendance_actual_week))
|
||||
|
||||
|
||||
@@ -210,3 +210,87 @@ class TestAutomaticLeaveDates(TestHrHolidaysBase):
|
||||
self.assertEqual(leave_form.number_of_hours_display, 0)
|
||||
self.assertEqual(leave_form.date_from, datetime(2019, 9, 3, 6, 0, 0))
|
||||
self.assertEqual(leave_form.date_to, datetime(2019, 9, 3, 10, 0, 0))
|
||||
|
||||
def test_2weeks_calendar(self):
|
||||
calendar = self.env['resource.calendar'].create({
|
||||
'name': 'auto next day',
|
||||
'two_weeks_calendar': True,
|
||||
'attendance_ids': [(5, 0, 0),
|
||||
(0, 0, {
|
||||
'name': 'monday morning odd week',
|
||||
'hour_from': 8,
|
||||
'hour_to': 12,
|
||||
'day_period': 'morning',
|
||||
'dayofweek': '0',
|
||||
'week_type': '0',
|
||||
}),
|
||||
(0, 0, {
|
||||
'name': 'monday morning even week',
|
||||
'hour_from': 10,
|
||||
'hour_to': 12,
|
||||
'day_period': 'morning',
|
||||
'dayofweek': '0',
|
||||
'week_type': '1',
|
||||
})]
|
||||
})
|
||||
employee = self.employee_emp
|
||||
employee.resource_calendar_id = calendar
|
||||
|
||||
with Form(self.env['hr.leave']) as leave_form:
|
||||
leave_form.employee_id = employee
|
||||
leave_form.holiday_status_id = self.leave_type
|
||||
# even week, works 2 hours
|
||||
leave_form.request_date_from = date(2019, 9, 2)
|
||||
leave_form.request_date_to = date(2019, 9, 2)
|
||||
leave_form.request_unit_half = True
|
||||
leave_form.request_date_from_period = 'am'
|
||||
|
||||
self.assertEqual(leave_form.number_of_days_display, 1)
|
||||
self.assertEqual(leave_form.number_of_hours_display, 2)
|
||||
self.assertEqual(leave_form.date_from, datetime(2019, 9, 2, 8, 0, 0))
|
||||
self.assertEqual(leave_form.date_to, datetime(2019, 9, 2, 10, 0, 0))
|
||||
|
||||
with Form(self.env['hr.leave']) as leave_form:
|
||||
leave_form.employee_id = employee
|
||||
leave_form.holiday_status_id = self.leave_type
|
||||
# odd week, works 4 hours
|
||||
leave_form.request_date_from = date(2019, 9, 9)
|
||||
leave_form.request_date_to = date(2019, 9, 9)
|
||||
leave_form.request_unit_half = True
|
||||
leave_form.request_date_from_period = 'am'
|
||||
|
||||
self.assertEqual(leave_form.number_of_days_display, 1)
|
||||
self.assertEqual(leave_form.number_of_hours_display, 4)
|
||||
self.assertEqual(leave_form.date_from, datetime(2019, 9, 9, 6, 0, 0))
|
||||
self.assertEqual(leave_form.date_to, datetime(2019, 9, 9, 10, 0, 0))
|
||||
|
||||
def test_2weeks_calendar_next_week(self):
|
||||
calendar = self.env['resource.calendar'].create({
|
||||
'name': 'auto next day',
|
||||
'two_weeks_calendar': True,
|
||||
'attendance_ids': [(5, 0, 0),
|
||||
(0, 0, {
|
||||
'name': 'monday morning odd week',
|
||||
'hour_from': 8,
|
||||
'hour_to': 12,
|
||||
'day_period': 'morning',
|
||||
'dayofweek': '0',
|
||||
'week_type': '0',
|
||||
})]
|
||||
})
|
||||
employee = self.employee_emp
|
||||
employee.resource_calendar_id = calendar
|
||||
|
||||
with Form(self.env['hr.leave']) as leave_form:
|
||||
leave_form.employee_id = employee
|
||||
leave_form.holiday_status_id = self.leave_type
|
||||
# even week, does not work
|
||||
leave_form.request_date_from = date(2019, 9, 2)
|
||||
leave_form.request_date_to = date(2019, 9, 2)
|
||||
leave_form.request_unit_half = True
|
||||
leave_form.request_date_from_period = 'am'
|
||||
|
||||
self.assertEqual(leave_form.number_of_days_display, 0)
|
||||
self.assertEqual(leave_form.number_of_hours_display, 0)
|
||||
self.assertEqual(leave_form.date_from, datetime(2019, 9, 2, 6, 0, 0))
|
||||
self.assertEqual(leave_form.date_to, datetime(2019, 9, 2, 10, 0, 0))
|
||||
|
||||
Reference in New Issue
Block a user