From 2bbae8e70eaac92550d27deb4bc5c02ee8cbbd35 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Wed, 8 Jan 2020 11:20:04 +0000 Subject: [PATCH] [FIX] hr_holidays: Fix number_of_hours_display computation Impacted versions: 13.0 Steps to reproduce: Add employee, allocate paid leave, set leave in hours. Standard workweek is set to 40 hours. 5 days 8h per day Global Time off: Dec.25 00:00:00 - Dec.26 23:59:59 Employee requests one week of leave, during christmas (dec.25 and dec. 26 in the week). Manager approves. Current behavior: Before approval the total hours in the request is 24. The manager approves and the total hours change to 40. Total remaining hours is also -40. Expected behavior: After approval the requested hours should not change and remain 24. The total remaining hours should also be -24. This is a similar issue as issue #41848 which has been fixed in #42710 TaskID: 2169161 Closes #42877 closes odoo/odoo#42924 closes odoo/odoo#42983 Original-signed-off-by: Yannick Tivisse (yti) X-original-commit: 11a5e3d09dd57d51813fc8151c30a619d4f368b5 Signed-off-by: Yannick Tivisse (yti) --- addons/hr_holidays/models/hr_leave.py | 3 +- .../hr_holidays/tests/test_leave_requests.py | 53 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index ed6bbc3f667..ad19d8f3007 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -485,7 +485,8 @@ class HolidaysRequest(models.Model): start_dt = start_dt.replace(tzinfo=UTC) if not end_dt.tzinfo: end_dt = end_dt.replace(tzinfo=UTC) - intervals = calendar._attendance_intervals(start_dt, end_dt, holiday.employee_id) + intervals = calendar._attendance_intervals(start_dt, end_dt, holiday.employee_id) \ + - calendar._leave_intervals(start_dt, end_dt, None) # Substract Global Leaves number_of_hours = sum((stop - start).total_seconds() / 3600 for start, stop, dummy in intervals) else: number_of_hours = holiday._get_number_of_days(holiday.date_from, holiday.date_to, holiday.employee_id.id)['hours'] diff --git a/addons/hr_holidays/tests/test_leave_requests.py b/addons/hr_holidays/tests/test_leave_requests.py index 49e9d340f68..c127bf26298 100644 --- a/addons/hr_holidays/tests/test_leave_requests.py +++ b/addons/hr_holidays/tests/test_leave_requests.py @@ -252,6 +252,9 @@ class TestLeaveRequests(TestHrHolidaysCommon): self.assertEqual(leave.date_to, datetime(2019, 5, 6, 5, 0, 0), "It should have been localized before saving in UTC") def test_number_of_hours_display(self): + # Test that the field number_of_hours_dispay doesn't change + # after time off validation, as it takes the attendances + # minus the resource leaves to compute that field. calendar = self.env['resource.calendar'].create({ 'name': 'Monday Morning Else Full Time 38h/week', 'hours_per_day': 7.6, @@ -312,3 +315,53 @@ class TestLeaveRequests(TestHrHolidaysCommon): self.assertEqual(leave2.number_of_hours_display, 4) leave2.action_validate() self.assertEqual(leave2.number_of_hours_display, 4) + + def test_number_of_hours_display_global_leave(self): + # Check that the field number_of_hours_display + # takes the global leaves into account, even + # after validation + calendar = self.env['resource.calendar'].create({ + 'name': 'Classic 40h/week', + 'hours_per_day': 8.0, + 'attendance_ids': [ + (0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}), + (0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}), + (0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}), + (0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}), + (0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}), + (0, 0, {'name': 'Wednesday Afternoon', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}), + (0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}), + (0, 0, {'name': 'Thursday Afternoon', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}), + (0, 0, {'name': 'Friday Morning', 'dayofweek': '4', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}), + (0, 0, {'name': 'Friday Afternoon', 'dayofweek': '4', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}) + ], + 'global_leave_ids': [(0, 0, { + 'name': 'Christmas Leave', + 'date_from': fields.Datetime.from_string('2019-12-25 00:00:00'), + 'date_to': fields.Datetime.from_string('2019-12-26 23:59:59'), + 'resource_id': False, + 'time_type': 'leave', + })] + }) + employee = self.employee_emp + employee.resource_calendar_id = calendar + self.env.user.company_id.resource_calendar_id = calendar + leave_type = self.env['hr.leave.type'].create({ + 'name': 'Sick', + 'request_unit': 'hour', + 'leave_validation_type': 'both', + 'allocation_type': 'no', + }) + leave1 = self.env['hr.leave'].create({ + 'name': 'Sick 1 week during christmas snif', + 'employee_id': employee.id, + 'holiday_status_id': leave_type.id, + 'date_from': fields.Datetime.from_string('2019-12-23 06:00:00'), + 'date_to': fields.Datetime.from_string('2019-12-27 20:00:00'), + 'number_of_days': 5, + }) + self.assertEqual(leave1.number_of_hours_display, 24) + leave1.action_approve() + self.assertEqual(leave1.number_of_hours_display, 24) + leave1.action_validate() + self.assertEqual(leave1.number_of_hours_display, 24)