From b50adfea083a424cda224e3eede25cbf5266e954 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 29 Jun 2026 09:53:53 +0000 Subject: [PATCH 1/4] [14.0][IMP] project_timesheet_hours_only --- project_timesheet_hours_only/__manifest__.py | 2 +- .../models/sale_order.py | 21 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/project_timesheet_hours_only/__manifest__.py b/project_timesheet_hours_only/__manifest__.py index 32ef5420..47403c99 100644 --- a/project_timesheet_hours_only/__manifest__.py +++ b/project_timesheet_hours_only/__manifest__.py @@ -5,7 +5,7 @@ "name": "Project Timesheet Hours Only", "summary": "Filter project timesheet smart button to " "exclude material consumption and show hours only", - "version": "14.0.1.1.0", + "version": "14.0.1.2.0", "category": "Project", "author": "Numigi", "website": "https://www.numigi.com", diff --git a/project_timesheet_hours_only/models/sale_order.py b/project_timesheet_hours_only/models/sale_order.py index 09ebf7c2..c85e62de 100644 --- a/project_timesheet_hours_only/models/sale_order.py +++ b/project_timesheet_hours_only/models/sale_order.py @@ -10,27 +10,19 @@ class SaleOrder(models.Model): @api.depends('analytic_account_id.line_ids') def _compute_timesheet_ids(self): - # Call the original method to retrieve the standard timesheets. super(SaleOrder, self)._compute_timesheet_ids() - for order in self: - # Filter the results using the same logic (t.task_id) to keep - # actual labor hours only and exclude material consumption. - order.timesheet_ids = order.timesheet_ids.filtered(lambda t: t.task_id) - - # Update the counter displayed on the smart button. + order.timesheet_ids = order.timesheet_ids.filtered( + lambda t: t.task_id and t.project_id in order.project_ids + ) order.timesheet_count = len(order.timesheet_ids) - # Note: the 'timesheet_total_duration' field updates by itself - # since it depends on the 'timesheet_ids' we just filtered. - def action_view_timesheet(self): - # Get the action from the original smart button. action = super(SaleOrder, self).action_view_timesheet() - # Restrict the displayed lines to those linked to a task. if isinstance(action, dict) and action.get('domain'): action['domain'].append(('task_id', '!=', False)) + action['domain'].append(('project_id', 'in', self.project_ids.ids)) return action @@ -43,4 +35,7 @@ def _timesheet_compute_delivered_quantity_domain(self): # analytic lines linked to a task (actual timesheets) are counted, # material consumption (task_id == False) is excluded. domain = super()._timesheet_compute_delivered_quantity_domain() - return expression.AND([domain, [('task_id', '!=', False)]]) + project_ids = self.order_id.project_ids.ids + domain = expression.AND([domain, [('task_id', '!=', False)]]) + domain = expression.AND([domain, [('project_id', 'in', project_ids)]]) + return domain From 3a426aa8f3d1a58f253a941aa0a4ad21c3403e5d Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 29 Jun 2026 10:02:01 +0000 Subject: [PATCH 2/4] [14.0][IMP] project_timesheet_hours_only --- .../tests/test_sale_order_qty_delivered.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py b/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py index bec66c72..ebe1e1c3 100644 --- a/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py +++ b/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py @@ -43,6 +43,7 @@ def setUpClass(cls): cls.order = cls.env["sale.order"].create({ "partner_id": cls.partner.id, + "analytic_account_id": cls.analytic_account.id, "order_line": [(0, 0, { "product_id": cls.service_product.id, "product_uom_qty": 20.0, @@ -50,6 +51,8 @@ def setUpClass(cls): })], }) cls.order_line = cls.order.order_line + cls.project.write({"sale_line_id": cls.order_line.id}) + cls.task.write({"sale_line_id": cls.order_line.id}) def _create_analytic_line(self, unit_amount, task=None): return self.env["account.analytic.line"].create({ From a3d3feff9a95f791785784b77940442fb8105eed Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 29 Jun 2026 10:16:52 +0000 Subject: [PATCH 3/4] [14.0][IMP] project_timesheet_hours_only --- .../tests/test_sale_order_qty_delivered.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py b/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py index ebe1e1c3..54e3d812 100644 --- a/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py +++ b/project_timesheet_hours_only/tests/test_sale_order_qty_delivered.py @@ -51,8 +51,14 @@ def setUpClass(cls): })], }) cls.order_line = cls.order.order_line - cls.project.write({"sale_line_id": cls.order_line.id}) - cls.task.write({"sale_line_id": cls.order_line.id}) + cls.project.write({ + "sale_line_id": cls.order_line.id, + "sale_order_id": cls.order.id, + }) + cls.task.write({ + "sale_line_id": cls.order_line.id, + "sale_order_id": cls.order.id, + }) def _create_analytic_line(self, unit_amount, task=None): return self.env["account.analytic.line"].create({ From 12b43bdde9f89023993679a98ba1e35456afeb22 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 29 Jun 2026 10:39:10 +0000 Subject: [PATCH 4/4] [14.0][IMP] project_timesheet_hours_only --- project_timesheet_hours_only/models/sale_order.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/project_timesheet_hours_only/models/sale_order.py b/project_timesheet_hours_only/models/sale_order.py index c85e62de..e3891c1a 100644 --- a/project_timesheet_hours_only/models/sale_order.py +++ b/project_timesheet_hours_only/models/sale_order.py @@ -35,7 +35,4 @@ def _timesheet_compute_delivered_quantity_domain(self): # analytic lines linked to a task (actual timesheets) are counted, # material consumption (task_id == False) is excluded. domain = super()._timesheet_compute_delivered_quantity_domain() - project_ids = self.order_id.project_ids.ids - domain = expression.AND([domain, [('task_id', '!=', False)]]) - domain = expression.AND([domain, [('project_id', 'in', project_ids)]]) - return domain + return expression.AND([domain, [('task_id', '!=', False)]])