From 1ed41ee1615fdcd141827fa67efb56ee6269d975 Mon Sep 17 00:00:00 2001 From: mafo-odoo Date: Thu, 23 Jun 2022 11:30:15 +0000 Subject: [PATCH] [FIX] project_timesheet_holidays: reset timesheets when global holiday has calendar edited Steps to reproduce: - Install Time off and timesheet modules - Create a public holiday with no "working hours" - Then edit it and add it with working hours used by some employees Expected behavior: Adding the working hours makes that the global time off meets the requirements to create timesheets. Then the employee related to the new "working hours" is going to have timesheets created for this holiday. Current behavior: No timesheet is created. Explanation: The write function of the global time off only updated timesheets when the dates where modified. We add the update in the calendar_id modification case and with it the new conditions to create the timesheets. (working hours = calendar_id) opw-2879882 closes odoo/odoo#96226 X-original-commit: a255a743b5296570aab166a5e275a323a1792b60 Signed-off-by: Laurent Stukkens (ltu) --- .../models/resource_calendar_leaves.py | 21 +++++------ .../tests/test_timesheet_global_time_off.py | 36 +++++++++++++++++++ 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/addons/project_timesheet_holidays/models/resource_calendar_leaves.py b/addons/project_timesheet_holidays/models/resource_calendar_leaves.py index 90bef97cfcd..9e208eabb7b 100644 --- a/addons/project_timesheet_holidays/models/resource_calendar_leaves.py +++ b/addons/project_timesheet_holidays/models/resource_calendar_leaves.py @@ -151,15 +151,16 @@ class ResourceCalendarLeaves(models.Model): return results def write(self, vals): - start_dates = self.mapped('date_from') - end_dates = self.mapped('date_to') + date_from, date_to, calendar_id = vals.get('date_from'), vals.get('date_to'), vals.get('calendar_id') + global_time_off_updated = self.env['resource.calendar.leaves'] + if date_from or date_to or 'calendar_id' in vals: + global_time_off_updated = self.filtered(lambda r: (date_from is not None and r.date_from != date_from) or (date_to is not None and r.date_to != date_to) or (calendar_id is not None and r.calendar_id.id != calendar_id)) + timesheets = global_time_off_updated.sudo().timesheet_ids + if timesheets: + timesheets.write({'global_leave_id': False}) + timesheets.unlink() result = super(ResourceCalendarLeaves, self).write(vals) - date_from, date_to = vals.get('date_from'), vals.get('date_to') - if date_from or date_to: - if any(start_date != date_from or end_date != date_to for start_date, end_date in zip(start_dates, end_dates)): - timesheets = self.mapped('timesheet_ids') - if timesheets: - timesheets.write({'global_leave_id': False}) - timesheets.unlink() - self._timesheet_create_lines() + if global_time_off_updated: + global_time_offs_with_leave_timesheet = global_time_off_updated.filtered(lambda r: not r.resource_id and r.calendar_id.company_id.internal_project_id and r.calendar_id.company_id.leave_timesheet_task_id) + global_time_offs_with_leave_timesheet._timesheet_create_lines() return result 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 689de00145a..0112b111992 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 @@ -139,3 +139,39 @@ class TestTimesheetGlobalTimeOff(common.TransactionCase): # No timesheet should have been created on the day off timesheet = self.env['account.analytic.line'].search([('date', '=', day_off), ('task_id', '=', leave_task.id)]) self.assertFalse(timesheet.id) + + # This tests that timesheets are created/deleted for every employee with the same calendar + # when a global time off has a calendar_id set/remove + def test_timesheet_creation_and_deletion_for_calendar_set_and_remove(self): + leave_start_datetime = datetime(2021, 1, 4, 7, 0, 0, 0) # This is a monday + leave_end_datetime = datetime(2021, 1, 8, 18, 0, 0, 0) # This is a friday + + global_time_off = 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 and full_time_employee_2 + # but none for part_time_employee + leave_task = self.test_company.leave_timesheet_task_id + + # Now we delete the calendar_id. The timesheets should be deleted too. + global_time_off.calendar_id = False + + self.assertFalse(leave_task.timesheet_ids.ids) + + # Now we reset the calendar_id. The timesheets should be created and have the right value. + global_time_off.calendar_id = self.test_company.resource_calendar_id.id + + timesheets_by_employee = defaultdict(lambda: self.env['account.analytic.line']) + for timesheet in leave_task.timesheet_ids: + timesheets_by_employee[timesheet.employee_id] |= timesheet + self.assertFalse(timesheets_by_employee.get(self.part_time_employee, False)) + self.assertEqual(len(timesheets_by_employee.get(self.full_time_employee)), 5) + self.assertEqual(len(timesheets_by_employee.get(self.full_time_employee_2)), 5) + + # The standard calendar is for 8 hours/day from 8 to 12 and from 13 to 17. + # So we need to check that the timesheets don't have more than 8 hours per day. + self.assertEqual(leave_task.effective_hours, 80)