From 062ae1905601f9298543376dc70ce6f51f745893 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Tue, 10 Mar 2026 17:46:58 +0000 Subject: [PATCH 1/6] TA#121 [IMP] project_task_analytic_lines : compute project from origin task id --- project_task_analytic_lines/__manifest__.py | 2 +- .../migrations/14.0.1.3.0/post-migration.py | 39 +++++++++++++++++++ .../models/account_analytic_line.py | 9 +++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 project_task_analytic_lines/migrations/14.0.1.3.0/post-migration.py diff --git a/project_task_analytic_lines/__manifest__.py b/project_task_analytic_lines/__manifest__.py index 0e9cadf3..b851e2f7 100644 --- a/project_task_analytic_lines/__manifest__.py +++ b/project_task_analytic_lines/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'Project Task Analytic Lines', - 'version': '14.0.1.2.1', + 'version': '14.0.1.3.0', 'author': 'Numigi', 'maintainer': 'Numigi', 'website': 'https://numigi.com/', diff --git a/project_task_analytic_lines/migrations/14.0.1.3.0/post-migration.py b/project_task_analytic_lines/migrations/14.0.1.3.0/post-migration.py new file mode 100644 index 00000000..9f1ed868 --- /dev/null +++ b/project_task_analytic_lines/migrations/14.0.1.3.0/post-migration.py @@ -0,0 +1,39 @@ +# © Numigi (tm) and all its contributors (https://numigi.com/r/home) +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +import logging + +_logger = logging.getLogger(__name__) + + +def migrate(cr, version): + """ + Post-migration script to update the project_id on existing analytic lines. + It uses raw SQL for better performance on large tables. + """ + if not version: + return + + _logger.info("Starting the update of project_id on analytic lines...") + + # Set project_id from task_id if available + cr.execute(""" + UPDATE account_analytic_line aal + SET project_id = pt.project_id + FROM project_task pt + WHERE aal.project_id IS NULL + AND aal.task_id = pt.id + AND pt.project_id IS NOT NULL + """) + + # Set project_id from origin_task_id if task_id did not provide a project + cr.execute(""" + UPDATE account_analytic_line aal + SET project_id = pt.project_id + FROM project_task pt + WHERE aal.project_id IS NULL + AND aal.origin_task_id = pt.id + AND pt.project_id IS NOT NULL + """) + + _logger.info("Analytic lines successfully updated.") diff --git a/project_task_analytic_lines/models/account_analytic_line.py b/project_task_analytic_lines/models/account_analytic_line.py index 817d145d..db4d1ee7 100644 --- a/project_task_analytic_lines/models/account_analytic_line.py +++ b/project_task_analytic_lines/models/account_analytic_line.py @@ -15,6 +15,15 @@ class AnalyticLine(models.Model): "project.task", "Origin Task", ondelete="restrict", index=True ) + @api.depends('task_id', 'task_id.project_id', 'origin_task_id', + 'origin_task_id.project_id') + def _compute_project_id(self): + for line in self.filtered(lambda line: not line.project_id): + if line.task_id.project_id: + line.project_id = line.task_id.project_id + if not line.task_id.project_id and line.origin_task_id.project_id: + line.project_id = line.origin_task_id.project_id + @api.model def search(self, args, offset=0, limit=None, order=None, count=False): args = args or [] From e3d60095167f2e69acf3c63702cd2587465eb17f Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Tue, 10 Mar 2026 18:03:21 +0000 Subject: [PATCH 2/6] TA#121 [IMP] project_task_analytic_lines : compute project from origin task id --- project_task_analytic_lines/tests/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/project_task_analytic_lines/tests/common.py b/project_task_analytic_lines/tests/common.py index 4a434960..d5e6f869 100644 --- a/project_task_analytic_lines/tests/common.py +++ b/project_task_analytic_lines/tests/common.py @@ -14,7 +14,9 @@ def setUpClass(cls): "login": "account_user", "email": "account_user@test.com", "groups_id": [ - (4, cls.env.ref("account.group_account_invoice").id)], + (4, cls.env.ref("account.group_account_invoice").id), + (4, cls.env.ref("analytic.group_analytic_accounting").id) + ], } ) From 9c23841fc5f3ba5e642703bc63aa612b1aa0c06a Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Tue, 10 Mar 2026 18:10:02 +0000 Subject: [PATCH 3/6] TA#121 [IMP] project_task_analytic_lines : TU compute projet_id --- project_task_analytic_lines/tests/common.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/project_task_analytic_lines/tests/common.py b/project_task_analytic_lines/tests/common.py index d5e6f869..0d646a8b 100644 --- a/project_task_analytic_lines/tests/common.py +++ b/project_task_analytic_lines/tests/common.py @@ -15,7 +15,9 @@ def setUpClass(cls): "email": "account_user@test.com", "groups_id": [ (4, cls.env.ref("account.group_account_invoice").id), - (4, cls.env.ref("analytic.group_analytic_accounting").id) + (4, cls.env.ref("analytic.group_analytic_accounting").id), + (4, cls.env.ref("project.group_project_user").id), + (4, cls.env.ref("hr_timesheet.group_hr_timesheet_user").id), ], } ) From cb97dbc436d2527f699d37eb6dbee00a86e12e20 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Tue, 10 Mar 2026 18:17:35 +0000 Subject: [PATCH 4/6] TA#121 [IMP] project_task_analytic_lines : TU compute projet_id --- project_task_analytic_lines/tests/common.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/project_task_analytic_lines/tests/common.py b/project_task_analytic_lines/tests/common.py index 0d646a8b..0cbf7dea 100644 --- a/project_task_analytic_lines/tests/common.py +++ b/project_task_analytic_lines/tests/common.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- # © Numigi (tm) and all its contributors (https://numigi.com/r/home) # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). @@ -16,8 +17,8 @@ def setUpClass(cls): "groups_id": [ (4, cls.env.ref("account.group_account_invoice").id), (4, cls.env.ref("analytic.group_analytic_accounting").id), - (4, cls.env.ref("project.group_project_user").id), - (4, cls.env.ref("hr_timesheet.group_hr_timesheet_user").id), + (4, cls.env.ref("project.group_project_manager").id), + (4, cls.env.ref("hr_timesheet.group_timesheet_manager").id), ], } ) @@ -114,4 +115,5 @@ def _get_invoice_line_vals(cls, **kwargs): def _validate_invoice(self): self.invoice.invoice_date = '2023-01-01' - self.invoice.sudo(self.account_user).action_post() + # In Odoo 14, use .with_user(user) instead of the deprecated .sudo(user) + self.invoice.with_user(self.account_user).action_post() From 03837b8afa52fec094d1620ea5311cd3439902a0 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 16 Mar 2026 17:53:15 +0000 Subject: [PATCH 5/6] TA#83121 [IMP] project_task_analytic_lines --- project_task_analytic_lines/__manifest__.py | 2 +- .../models/account_analytic_line.py | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/project_task_analytic_lines/__manifest__.py b/project_task_analytic_lines/__manifest__.py index b851e2f7..bade043d 100644 --- a/project_task_analytic_lines/__manifest__.py +++ b/project_task_analytic_lines/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'Project Task Analytic Lines', - 'version': '14.0.1.3.0', + 'version': '14.0.1.4.0', 'author': 'Numigi', 'maintainer': 'Numigi', 'website': 'https://numigi.com/', diff --git a/project_task_analytic_lines/models/account_analytic_line.py b/project_task_analytic_lines/models/account_analytic_line.py index db4d1ee7..5c7c029c 100644 --- a/project_task_analytic_lines/models/account_analytic_line.py +++ b/project_task_analytic_lines/models/account_analytic_line.py @@ -15,13 +15,13 @@ class AnalyticLine(models.Model): "project.task", "Origin Task", ondelete="restrict", index=True ) - @api.depends('task_id', 'task_id.project_id', 'origin_task_id', - 'origin_task_id.project_id') + @api.depends('task_id', 'task_id.project_id', 'origin_task_id') def _compute_project_id(self): for line in self.filtered(lambda line: not line.project_id): - if line.task_id.project_id: + if line.task_id and line.task_id.project_id: line.project_id = line.task_id.project_id - if not line.task_id.project_id and line.origin_task_id.project_id: + if not line.task_id and line.origin_task_id.project_id: + line.task_id = line.origin_task_id line.project_id = line.origin_task_id.project_id @api.model @@ -79,7 +79,6 @@ def _check_origin_task_and_project_match(self): @api.model_create_multi def create(self, vals_list): lines = super(AnalyticLine, self).create(vals_list) - for line in lines: if line.task_id: line.origin_task_id = line.task_id From e18d1ba5591bb483830236ee3774576734e5c9a6 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 16 Mar 2026 17:53:57 +0000 Subject: [PATCH 6/6] TA#83121 [IMP] project_task_analytic_lines --- project_task_analytic_lines/models/account_analytic_line.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project_task_analytic_lines/models/account_analytic_line.py b/project_task_analytic_lines/models/account_analytic_line.py index 5c7c029c..12ab934a 100644 --- a/project_task_analytic_lines/models/account_analytic_line.py +++ b/project_task_analytic_lines/models/account_analytic_line.py @@ -18,7 +18,7 @@ class AnalyticLine(models.Model): @api.depends('task_id', 'task_id.project_id', 'origin_task_id') def _compute_project_id(self): for line in self.filtered(lambda line: not line.project_id): - if line.task_id and line.task_id.project_id: + if line.task_id and line.task_id.project_id: line.project_id = line.task_id.project_id if not line.task_id and line.origin_task_id.project_id: line.task_id = line.origin_task_id