From 4659736fc478b279df26880d860111e1426aeefb Mon Sep 17 00:00:00 2001 From: mafo-odoo Date: Thu, 7 Jul 2022 08:00:53 +0000 Subject: [PATCH] [FIX] project_timesheet_holidays: create/remove global time off timesheets Before this commit, when the employee is generated with the salary configurator, the employee is archived since the employee will not directly start in the company. Even if the employee is archived and the timesheets are generated for this employee based on the global time offs found in the future. The problem is the timesheets cannot be created for archived employees and so a user error is raised. This problem could also happen if the user creates an archived employee. This commit fixes the issue by preventing the timesheets generation when the employee created is archived. When this employee will be updated and active field will be set to True, the timesheets generation will be applied. In the inverse use case, when the user will archive an employee and timesheets generated for the future global time offs will be removed. opw-2887727 opw-2870739 closes odoo/odoo#95644 X-original-commit: 160afba28d88ddd9d84856cc90639586bc2ea7b6 Related: odoo/enterprise#29273 Signed-off-by: Laurent Stukkens (ltu) Signed-off-by: Fockedey Martin (mafo) --- .../models/hr_employee.py | 28 ++++++++++++++---- .../tests/test_timesheet_global_time_off.py | 29 ++++++++++++++++++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/addons/project_timesheet_holidays/models/hr_employee.py b/addons/project_timesheet_holidays/models/hr_employee.py index dd8b109a210..c09ed520f68 100644 --- a/addons/project_timesheet_holidays/models/hr_employee.py +++ b/addons/project_timesheet_holidays/models/hr_employee.py @@ -16,13 +16,30 @@ class Employee(models.Model): # We need to create timesheet entries for the global time off that are already created # and are planned for after this employee creation date - # First we look for the global time off that are already planned after today - today = fields.Datetime.today() + self._create_future_public_holidays_timesheets(employees) + return employees + + def write(self, vals): + result = super(Employee, self).write(vals) + if 'active' in vals: + if vals.get('active'): + # Create future holiday timesheets + self._create_future_public_holidays_timesheets(self) + else: + # Delete future holiday timesheets + future_timesheets = self.env['account.analytic.line'].sudo().search([('global_leave_id', '!=', False), ('date', '>=', fields.date.today()), ('employee_id', 'in', self.ids)]) + future_timesheets.write({'global_leave_id': False}) + future_timesheets.unlink() + return result + + def _create_future_public_holidays_timesheets(self, employees): lines_vals = [] for employee in employees: - global_leaves = employee.resource_calendar_id.global_leave_ids.filtered(lambda l: l.date_from >= today) + if not employee.active: + continue + # First we look for the global time off that are already planned after today + global_leaves = employee.resource_calendar_id.global_leave_ids.filtered(lambda l: l.date_from >= fields.Datetime.today()) work_hours_data = global_leaves._work_time_per_day() - for global_time_off in global_leaves: for index, (day_date, work_hours_count) in enumerate(work_hours_data[global_time_off.id]): lines_vals.append( @@ -34,5 +51,4 @@ class Employee(models.Model): work_hours_count ) ) - self.env['account.analytic.line'].sudo().create(lines_vals) - return employees + return self.env['account.analytic.line'].sudo().create(lines_vals) diff --git a/addons/project_timesheet_holidays/tests/test_timesheet_global_time_off.py b/addons/project_timesheet_holidays/tests/test_timesheet_global_time_off.py index d717d53d109..a1739f75e1b 100644 --- a/addons/project_timesheet_holidays/tests/test_timesheet_global_time_off.py +++ b/addons/project_timesheet_holidays/tests/test_timesheet_global_time_off.py @@ -2,7 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from collections import defaultdict -from datetime import datetime +from datetime import datetime, timedelta from odoo import Command from odoo.tests import common @@ -89,6 +89,33 @@ class TestTimesheetGlobalTimeOff(common.TransactionCase): self.assertFalse(leave_task.timesheet_ids.ids) + def test_timesheet_creation_and_deletion_on_employee_archive(self): + """ Test the timesheets linked to the global time off in the future when the employee is archived """ + today = datetime.today() + leave_start_datetime = today + timedelta(days=-today.weekday(), weeks=1) # Next monday + leave_end_datetime = leave_start_datetime + timedelta(days=5) # Next friday + + self.env['resource.calendar.leaves'].create({ + 'name': 'Test', + 'calendar_id': self.test_company.resource_calendar_id.id, + 'date_from': leave_start_datetime, + 'date_to': leave_end_datetime, + }) + + # 5 Timesheets should have been created for full_time_employee + timesheets_full_time_employee = self.env['account.analytic.line'].search([('employee_id', '=', self.full_time_employee.id)]) + self.assertEqual(len(timesheets_full_time_employee), 5) + + # All timesheets should have been deleted for full_time_employee when he is archived + self.full_time_employee.active = False + timesheets_full_time_employee = self.env['account.analytic.line'].search([('employee_id', '=', self.full_time_employee.id)]) + self.assertEqual(len(timesheets_full_time_employee), 0) + + # 5 Timesheets should have been created for full_time_employee when he is unarchived + self.full_time_employee.active = True + timesheets_full_time_employee = self.env['account.analytic.line'].search([('employee_id', '=', self.full_time_employee.id)]) + self.assertEqual(len(timesheets_full_time_employee), 5) + # This tests that no timesheet are created for days when the employee is not supposed to work def test_no_timesheet_on_off_days(self): leave_start_datetime = datetime(2021, 1, 4, 7, 0, 0, 0) # This is a monday