From aba7b00cd829d7e887bc4e4aaf1459904ad6175a Mon Sep 17 00:00:00 2001 From: "Thomas Lefebvre (thle)" Date: Thu, 18 Jan 2024 09:44:58 +0100 Subject: [PATCH] [FIX] hr_timesheet: add fallback to current company to get UoM Steps to reproduce: ------------------- - install helpdesk_fsm and sale_timesheet; - to be in a multi-company environment; - create a new helpdesk team with "Timesheets", "Time Billing"; - the newly created project has no company; - create a service product that creates a task with UoM in hours in the newly created project for the helpdesk team; - create a sale order with this product with a quantity of 100 hours and confirm it; - in the helpdesk app (in the new team), create a ticket linked to the sale order line of the product (the customer is necessary); - on the ticket the "Remaining Hours on SO" is 100 hours; - create a timesheet directly in the tree view; - the remaining hours of the sale order are reduced; - create a timesheet from the timer; - the remaining hours of the sale order are not reduced; Cause: ------ During the link between the newly created timesheet and the ticket, we write to the `helpdesk_ticket_id` field (during the flush) in the `account.analytic.line` record. As a result, we pass in the override of the `write` method, which calls `_timesheet_preprocess`. Without a company on the project (or on the analytic account if there is one), the value `{'product_uom_id': False}` will be added to the values to be written to the timesheet. Without a unit of measurement, the timesheet will not be used to calculate the remaining hours. Solution: --------- Add a fallback on the current company if no company is found. opw-3651830 closes odoo/odoo#149917 X-original-commit: 2e5c13b0dea40f349e96cadf9d02fdb3c1746c7e Signed-off-by: Xavier Bol (xbo) --- addons/hr_timesheet/models/hr_timesheet.py | 2 +- addons/hr_timesheet/tests/test_performance.py | 4 +++- addons/hr_timesheet/tests/test_timesheet.py | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py index fc9282d7892..cbf2cbe305c 100644 --- a/addons/hr_timesheet/models/hr_timesheet.py +++ b/addons/hr_timesheet/models/hr_timesheet.py @@ -373,7 +373,7 @@ class AccountAnalyticLine(models.Model): vals['partner_id'] = data.partner_id.id if not vals.get('product_uom_id'): company = account_per_id[vals['account_id']].company_id or data.company_id - vals['product_uom_id'] = uom_id_per_company.get(company.id, company.project_time_mode_id.id) + vals['product_uom_id'] = uom_id_per_company.get(company.id, company.project_time_mode_id.id) or self.env.company.project_time_mode_id.id return vals_list def _timesheet_postprocess(self, values): diff --git a/addons/hr_timesheet/tests/test_performance.py b/addons/hr_timesheet/tests/test_performance.py index b5663d3d54e..f0d0082e573 100644 --- a/addons/hr_timesheet/tests/test_performance.py +++ b/addons/hr_timesheet/tests/test_performance.py @@ -2,7 +2,9 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo.addons.hr_timesheet.tests.test_timesheet import TestCommonTimesheet +from odoo.tests import tagged +@tagged('post_install', '-at_install') class TestPerformanceTimesheet(TestCommonTimesheet): def test_timesheet_preprocess(self): @@ -13,7 +15,7 @@ class TestPerformanceTimesheet(TestCommonTimesheet): } for i in range(17) for project in projects]) self.env.invalidate_all() self.env.registry.clear_cache() - with self.assertQueryCount(5): + with self.assertQueryCount(8): self.env['account.analytic.line']._timesheet_preprocess([ {'task_id': task.id} for task in tasks for _i in range(10) ]) diff --git a/addons/hr_timesheet/tests/test_timesheet.py b/addons/hr_timesheet/tests/test_timesheet.py index 92d7d6574ae..a571b33d4ab 100644 --- a/addons/hr_timesheet/tests/test_timesheet.py +++ b/addons/hr_timesheet/tests/test_timesheet.py @@ -594,6 +594,14 @@ class TestTimesheet(TestCommonTimesheet): self.assertEqual(timesheet_with_task.product_uom_id, self.task1.company_id.project_time_mode_id, "The product_uom_id of the timesheet should be equal to the task's company uom " "if the project's analytic account has no company_id") + # Remove the company also on the project to be sure we find a UoM + self.project_customer.company_id = False + timesheet_with_project.with_user(self.user_employee).write( + {'unit_amount': 2.0, 'project_id': self.project_customer.id}) + self.assertEqual(timesheet_with_project.product_uom_id, self.env.company.project_time_mode_id, + "The product_uom_id of the timesheet should be equal to the company uom " + "if the project's analytic account and the project have no company_id") + def test_create_timesheet_with_default_employee_in_context(self): timesheet = self.env['account.analytic.line'].with_context(default_employee_id=self.empl_employee.id).create({