From 7ab530bd2972b581db4fc20c56c65928a2d640be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20V=C3=A9zina?= Date: Wed, 5 Feb 2025 16:13:34 -0500 Subject: [PATCH] Fixe date deadline cascade --- .../__manifest__.py | 9 ++- .../data/res_config_settings_data.xml | 9 +++ .../models/__init__.py | 1 + .../models/project_task.py | 70 ++++++++++++++----- .../models/res_config_settings.py | 12 ++++ .../security/ir.model.access.csv | 2 + .../views/res_config_settings_views.xml | 19 +++++ .../views/update_deadline_wizard_view.xml | 26 ------- .../wizard/__init__.py | 3 - .../wizard/update_deadline_wizard.py | 18 ----- 10 files changed, 102 insertions(+), 67 deletions(-) create mode 100644 project_task_date_deadline_cascade_update/data/res_config_settings_data.xml create mode 100644 project_task_date_deadline_cascade_update/models/res_config_settings.py create mode 100644 project_task_date_deadline_cascade_update/security/ir.model.access.csv create mode 100644 project_task_date_deadline_cascade_update/views/res_config_settings_views.xml delete mode 100644 project_task_date_deadline_cascade_update/views/update_deadline_wizard_view.xml delete mode 100644 project_task_date_deadline_cascade_update/wizard/__init__.py delete mode 100644 project_task_date_deadline_cascade_update/wizard/update_deadline_wizard.py diff --git a/project_task_date_deadline_cascade_update/__manifest__.py b/project_task_date_deadline_cascade_update/__manifest__.py index f69aaf4..9601fda 100644 --- a/project_task_date_deadline_cascade_update/__manifest__.py +++ b/project_task_date_deadline_cascade_update/__manifest__.py @@ -9,10 +9,13 @@ 'author': 'Your Name', 'license': 'AGPL-3', 'website': 'https://www.yourwebsite.com', - 'depends': ['project'], + 'depends': [ + 'project', + 'project_enterprise' + ], 'data': [ - 'views/update_deadline_wizard_view.xml', - 'wizard/update_deadline_wizard.xml', + 'views/res_config_settings_views.xml', + 'data/res_config_settings_data.xml', ], 'installable': True, 'auto_install': False, diff --git a/project_task_date_deadline_cascade_update/data/res_config_settings_data.xml b/project_task_date_deadline_cascade_update/data/res_config_settings_data.xml new file mode 100644 index 0000000..11c1d09 --- /dev/null +++ b/project_task_date_deadline_cascade_update/data/res_config_settings_data.xml @@ -0,0 +1,9 @@ + + + + + project_task_date_deadline_cascade_update.enablecascade + False + + + diff --git a/project_task_date_deadline_cascade_update/models/__init__.py b/project_task_date_deadline_cascade_update/models/__init__.py index d44ba0c..0ce6827 100644 --- a/project_task_date_deadline_cascade_update/models/__init__.py +++ b/project_task_date_deadline_cascade_update/models/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from . import project_task +from . import res_config_settings diff --git a/project_task_date_deadline_cascade_update/models/project_task.py b/project_task_date_deadline_cascade_update/models/project_task.py index 0c6c545..86bd12f 100644 --- a/project_task_date_deadline_cascade_update/models/project_task.py +++ b/project_task_date_deadline_cascade_update/models/project_task.py @@ -1,24 +1,60 @@ # -*- coding: utf-8 -*- +import logging from odoo import api, fields, models -from odoo.exceptions import UserError -from odoo import _ + +_logger = logging.getLogger(__name__) class ProjectTask(models.Model): _inherit = 'project.task' + - @api.model - def write(self, vals): - res = super(ProjectTask, self).write(vals) - if 'date_deadline' in vals: - for task in self: - if task.child_ids: - return { - 'name': _('Update Deadline'), - 'type': 'ir.actions.act_window', - 'res_model': 'update.deadline.wizard', - 'view_mode': 'form', - 'target': 'new', - 'context': {'active_ids': self.ids}, - } - return res + def _update_child_dates_recursive(self, date_deadline=None, planned_date_begin=None): + """Update dates for all subtasks at all levels using _get_all_subtasks. + + Args: + date_deadline: The deadline date to set for all subtasks + planned_date_begin: The planned start date to set for all subtasks + """ + if not self.child_ids: + return + + _logger.info( + 'Starting update for all subtasks of: %s (ID: %s)', + self.name, self.id + ) + + # Get all subtasks at all levels + all_subtasks = self._get_all_subtasks() + + if all_subtasks: + # Update both dates for all subtasks at once + values = { + 'date_deadline': date_deadline, + 'planned_date_begin': planned_date_begin + } + _logger.info( + 'Updating %d subtasks with values: %s', + len(all_subtasks), values + ) + all_subtasks.write(values) + + @api.onchange('date_deadline') + def _onchange_date_deadline(self): + """When parent task deadline changes, update all child tasks deadlines and planned dates recursively.""" + if self.date_deadline and self.child_ids and not self.env.context.get('skip_onchange'): + _logger.info('Recursively updating deadline and planned date for all subtasks of: %s', self.name) + self.with_context(skip_onchange=True)._update_child_dates_recursive( + date_deadline=self.date_deadline, + planned_date_begin=self.planned_date_begin # Always pass planned_date_begin + ) + + @api.onchange('planned_date_begin') + def _onchange_planned_date_begin(self): + """When parent task planned date changes, update all child tasks planned dates and deadlines recursively.""" + if self.planned_date_begin and self.child_ids and not self.env.context.get('skip_onchange'): + _logger.info('Recursively updating planned date and deadline for all subtasks of: %s', self.name) + self.with_context(skip_onchange=True)._update_child_dates_recursive( + planned_date_begin=self.planned_date_begin, + date_deadline=self.date_deadline # Always pass date_deadline + ) diff --git a/project_task_date_deadline_cascade_update/models/res_config_settings.py b/project_task_date_deadline_cascade_update/models/res_config_settings.py new file mode 100644 index 0000000..744e8dd --- /dev/null +++ b/project_task_date_deadline_cascade_update/models/res_config_settings.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + enable_task_deadline_cascade = fields.Boolean( + string='Enable Task Deadline Cascade', + config_parameter='project_task_date_deadline_cascade_update.enablecascade' + ) diff --git a/project_task_date_deadline_cascade_update/security/ir.model.access.csv b/project_task_date_deadline_cascade_update/security/ir.model.access.csv new file mode 100644 index 0000000..83995b4 --- /dev/null +++ b/project_task_date_deadline_cascade_update/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_update_deadline_wizard,access.update.deadline.wizard,model_update_deadline_wizard,project.group_project_user,1,1,1,1 diff --git a/project_task_date_deadline_cascade_update/views/res_config_settings_views.xml b/project_task_date_deadline_cascade_update/views/res_config_settings_views.xml new file mode 100644 index 0000000..5517118 --- /dev/null +++ b/project_task_date_deadline_cascade_update/views/res_config_settings_views.xml @@ -0,0 +1,19 @@ + + + + res.config.settings.view.form.inherit.project.task.deadline + res.config.settings + 99 + + + + + +
+ Enable deadline cascade update for project tasks +
+
+
+
+
+
diff --git a/project_task_date_deadline_cascade_update/views/update_deadline_wizard_view.xml b/project_task_date_deadline_cascade_update/views/update_deadline_wizard_view.xml deleted file mode 100644 index 8c6b039..0000000 --- a/project_task_date_deadline_cascade_update/views/update_deadline_wizard_view.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - update.deadline.wizard.form - update.deadline.wizard - -
- - - -
-
-
-
-
- - - Update Deadline - update.deadline.wizard - form - - new - -
diff --git a/project_task_date_deadline_cascade_update/wizard/__init__.py b/project_task_date_deadline_cascade_update/wizard/__init__.py deleted file mode 100644 index 0e22159..0000000 --- a/project_task_date_deadline_cascade_update/wizard/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# -*- coding: utf-8 -*- - -from . import update_deadline_wizard diff --git a/project_task_date_deadline_cascade_update/wizard/update_deadline_wizard.py b/project_task_date_deadline_cascade_update/wizard/update_deadline_wizard.py deleted file mode 100644 index be76fd2..0000000 --- a/project_task_date_deadline_cascade_update/wizard/update_deadline_wizard.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -from odoo import api, fields, models - - -class UpdateDeadlineWizard(models.TransientModel): - _name = 'update.deadline.wizard' - _description = 'Update Deadline Wizard' - - apply_to_children = fields.Boolean(string='Apply to Child Tasks', default=False) - - def update_deadline(self): - context = dict(self._context or {}) - active_ids = context.get('active_ids', []) - tasks = self.env['project.task'].browse(active_ids) - for task in tasks: - if task.child_ids and self.apply_to_children: - task.child_ids.write({'date_deadline': task.date_deadline})