From c0ba518e63e2863e251ea3cc385fdf81246692ee Mon Sep 17 00:00:00 2001 From: Abdellatif BENZBIRIA Date: Tue, 18 Mar 2025 22:51:54 +0000 Subject: [PATCH 1/5] Update project_milestone.py --- .../models/project_milestone.py | 71 +++++++++---------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/project_milestone_timeline_dynamic/models/project_milestone.py b/project_milestone_timeline_dynamic/models/project_milestone.py index b522a49e..c335ad7a 100644 --- a/project_milestone_timeline_dynamic/models/project_milestone.py +++ b/project_milestone_timeline_dynamic/models/project_milestone.py @@ -10,51 +10,44 @@ class ProjectMilestone(models.Model): @api.constrains('start_date') def _check_start_date_and_dependencies_end_date(self): - sorted_child_ids = self.child_ids.sorted( - key='target_date', reverse=True) - child_last_end_dates = self.child_ids.sorted( - key='target_date', reverse=True).mapped('target_date') + for milestone in self: + sorted_child_ids = milestone.child_ids.sorted( + key='target_date', reverse=True) + child_last_end_dates = milestone.child_ids.mapped('target_date') + + if child_last_end_dates and milestone.start_date and \ + milestone.start_date < max(child_last_end_dates): + raise ValidationError( + _('The milestone %s - %s is dependent on this ' + 'milestone and has a %s end date.' + ) % (sorted_child_ids[0].name, + sorted_child_ids[0].project_id.name, + fields.Date.to_string(max(child_last_end_dates))) + ) + + def _check_child_milestones_target_date(self): + child_last_end_dates = self.child_ids.mapped('target_date') if child_last_end_dates and self.start_date and \ - self.start_date < child_last_end_dates[0]: - raise ValidationError( - _('The milestone %s - %s is dependent on this ' - 'milestone and has a %s end date.' - % (sorted_child_ids[0].name, - sorted_child_ids[0].project_id.name, - fields.Date.to_string(child_last_end_dates[0])) - ) - ) - - def _check_child_milestones_target_date(self, milestone): - child_last_end_dates = milestone.child_ids.sorted( - key='target_date', reverse=True).mapped('target_date') - if child_last_end_dates and \ - (not milestone.start_date or milestone.start_date <= \ - child_last_end_dates[0]): - milestone_duration = \ - milestone.target_date - milestone.start_date - milestone.start_date = \ - child_last_end_dates[0] + timedelta(days=1) - milestone.target_date = \ - milestone.start_date + milestone_duration - - def _get_parent_milestone(self, milestone): - self._cr.execute( - 'SELECT milestone_id ' - 'FROM "rel_project_milestone_dependencies"' - ' WHERE child_id=%s' % milestone.id) - milestone_id = self._cr.fetchone() + self.start_date <= max(child_last_end_dates): + milestone_duration = self.target_date - self.start_date + self.start_date = max(child_last_end_dates) + timedelta(days=1) + self.target_date = self.start_date + milestone_duration + + def _get_parent_milestone(self): + self.env.cr.execute( + 'SELECT milestone_id FROM rel_project_milestone_dependencies ' + 'WHERE child_id = %s', (self.id,)) + milestone_id = self.env.cr.fetchone() return self.env['project.milestone'].browse(milestone_id[0]) \ if milestone_id else None - @api.multi def write(self, vals): for milestone in self: - res = super(ProjectMilestone, milestone).write(vals) if 'child_ids' in vals: - self._check_child_milestones_target_date(milestone) + milestone._check_child_milestones_target_date() if 'target_date' in vals: - parent_milestone = self._get_parent_milestone(milestone) + parent_milestone = milestone._get_parent_milestone() if parent_milestone: - self._check_child_milestones_target_date(parent_milestone) - return res + parent_milestone._check_child_milestones_target_date() + + return super(ProjectMilestone, self).write(vals) From bc4c5073a43cfa38613e715575cb1c15027ae0a3 Mon Sep 17 00:00:00 2001 From: Abdellatif BENZBIRIA Date: Tue, 18 Mar 2025 23:04:15 +0000 Subject: [PATCH 2/5] Update project_milestone.py --- .../models/project_milestone.py | 71 ++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/project_milestone_timeline_dynamic/models/project_milestone.py b/project_milestone_timeline_dynamic/models/project_milestone.py index c335ad7a..79d24680 100644 --- a/project_milestone_timeline_dynamic/models/project_milestone.py +++ b/project_milestone_timeline_dynamic/models/project_milestone.py @@ -10,44 +10,51 @@ class ProjectMilestone(models.Model): @api.constrains('start_date') def _check_start_date_and_dependencies_end_date(self): - for milestone in self: - sorted_child_ids = milestone.child_ids.sorted( - key='target_date', reverse=True) - child_last_end_dates = milestone.child_ids.mapped('target_date') - - if child_last_end_dates and milestone.start_date and \ - milestone.start_date < max(child_last_end_dates): - raise ValidationError( - _('The milestone %s - %s is dependent on this ' - 'milestone and has a %s end date.' - ) % (sorted_child_ids[0].name, - sorted_child_ids[0].project_id.name, - fields.Date.to_string(max(child_last_end_dates))) - ) - - def _check_child_milestones_target_date(self): - child_last_end_dates = self.child_ids.mapped('target_date') + sorted_child_ids = self.child_ids.sorted( + key='target_date', reverse=True) + child_last_end_dates = self.child_ids.sorted( + key='target_date', reverse=True).mapped('target_date') if child_last_end_dates and self.start_date and \ - self.start_date <= max(child_last_end_dates): - milestone_duration = self.target_date - self.start_date - self.start_date = max(child_last_end_dates) + timedelta(days=1) - self.target_date = self.start_date + milestone_duration - - def _get_parent_milestone(self): - self.env.cr.execute( - 'SELECT milestone_id FROM rel_project_milestone_dependencies ' - 'WHERE child_id = %s', (self.id,)) - milestone_id = self.env.cr.fetchone() + self.start_date < child_last_end_dates[0]: + raise ValidationError( + _('The milestone %s - %s is dependent on this ' + 'milestone and has a %s end date.' + % (sorted_child_ids[0].name, + sorted_child_ids[0].project_id.name, + fields.Date.to_string(child_last_end_dates[0])) + ) + ) + + def _check_child_milestones_target_date(self, milestone): + child_last_end_dates = milestone.child_ids.sorted( + key='target_date', reverse=True).mapped('target_date') + if child_last_end_dates and \ + (not milestone.start_date or milestone.start_date <= \ + child_last_end_dates[0]): + milestone_duration = \ + milestone.target_date - milestone.start_date + milestone.start_date = \ + child_last_end_dates[0] + timedelta(days=1) + milestone.target_date = \ + milestone.start_date + milestone_duration + + def _get_parent_milestone(self, milestone): + self._cr.execute( + 'SELECT milestone_id ' + 'FROM "rel_project_milestone_dependencies"' + ' WHERE child_id=%s' % milestone.id) + milestone_id = self._cr.fetchone() return self.env['project.milestone'].browse(milestone_id[0]) \ if milestone_id else None + @api.multi def write(self, vals): for milestone in self: + res = super(ProjectMilestone, milestone).write(vals) if 'child_ids' in vals: - milestone._check_child_milestones_target_date() + milestone._check_child_milestones_target_date(milestone) if 'target_date' in vals: - parent_milestone = milestone._get_parent_milestone() + parent_milestone = self._get_parent_milestone(milestone) if parent_milestone: - parent_milestone._check_child_milestones_target_date() - - return super(ProjectMilestone, self).write(vals) + milestone._check_child_milestones_target_date(parent_milestone) + return res From 5d9be118e9e9a836f0d2a75d9ced005a4b37cc8d Mon Sep 17 00:00:00 2001 From: Abdellatif BENZBIRIA Date: Tue, 18 Mar 2025 23:50:13 +0000 Subject: [PATCH 3/5] Update project_milestone.py --- .../models/project_milestone.py | 71 +++++++++---------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/project_milestone_timeline_dynamic/models/project_milestone.py b/project_milestone_timeline_dynamic/models/project_milestone.py index 79d24680..c335ad7a 100644 --- a/project_milestone_timeline_dynamic/models/project_milestone.py +++ b/project_milestone_timeline_dynamic/models/project_milestone.py @@ -10,51 +10,44 @@ class ProjectMilestone(models.Model): @api.constrains('start_date') def _check_start_date_and_dependencies_end_date(self): - sorted_child_ids = self.child_ids.sorted( - key='target_date', reverse=True) - child_last_end_dates = self.child_ids.sorted( - key='target_date', reverse=True).mapped('target_date') + for milestone in self: + sorted_child_ids = milestone.child_ids.sorted( + key='target_date', reverse=True) + child_last_end_dates = milestone.child_ids.mapped('target_date') + + if child_last_end_dates and milestone.start_date and \ + milestone.start_date < max(child_last_end_dates): + raise ValidationError( + _('The milestone %s - %s is dependent on this ' + 'milestone and has a %s end date.' + ) % (sorted_child_ids[0].name, + sorted_child_ids[0].project_id.name, + fields.Date.to_string(max(child_last_end_dates))) + ) + + def _check_child_milestones_target_date(self): + child_last_end_dates = self.child_ids.mapped('target_date') if child_last_end_dates and self.start_date and \ - self.start_date < child_last_end_dates[0]: - raise ValidationError( - _('The milestone %s - %s is dependent on this ' - 'milestone and has a %s end date.' - % (sorted_child_ids[0].name, - sorted_child_ids[0].project_id.name, - fields.Date.to_string(child_last_end_dates[0])) - ) - ) - - def _check_child_milestones_target_date(self, milestone): - child_last_end_dates = milestone.child_ids.sorted( - key='target_date', reverse=True).mapped('target_date') - if child_last_end_dates and \ - (not milestone.start_date or milestone.start_date <= \ - child_last_end_dates[0]): - milestone_duration = \ - milestone.target_date - milestone.start_date - milestone.start_date = \ - child_last_end_dates[0] + timedelta(days=1) - milestone.target_date = \ - milestone.start_date + milestone_duration - - def _get_parent_milestone(self, milestone): - self._cr.execute( - 'SELECT milestone_id ' - 'FROM "rel_project_milestone_dependencies"' - ' WHERE child_id=%s' % milestone.id) - milestone_id = self._cr.fetchone() + self.start_date <= max(child_last_end_dates): + milestone_duration = self.target_date - self.start_date + self.start_date = max(child_last_end_dates) + timedelta(days=1) + self.target_date = self.start_date + milestone_duration + + def _get_parent_milestone(self): + self.env.cr.execute( + 'SELECT milestone_id FROM rel_project_milestone_dependencies ' + 'WHERE child_id = %s', (self.id,)) + milestone_id = self.env.cr.fetchone() return self.env['project.milestone'].browse(milestone_id[0]) \ if milestone_id else None - @api.multi def write(self, vals): for milestone in self: - res = super(ProjectMilestone, milestone).write(vals) if 'child_ids' in vals: - milestone._check_child_milestones_target_date(milestone) + milestone._check_child_milestones_target_date() if 'target_date' in vals: - parent_milestone = self._get_parent_milestone(milestone) + parent_milestone = milestone._get_parent_milestone() if parent_milestone: - milestone._check_child_milestones_target_date(parent_milestone) - return res + parent_milestone._check_child_milestones_target_date() + + return super(ProjectMilestone, self).write(vals) From 194c6bf6ed27aef050226b9c9a1eab566cf8dcf3 Mon Sep 17 00:00:00 2001 From: "Lanto R." <124650562+lanto-razafindrabe@users.noreply.github.com> Date: Wed, 19 Mar 2025 06:05:43 +0300 Subject: [PATCH 4/5] TA#73243 [12.0][CHG] project_milestone_timeline_dynamic : version and quotes --- .../__manifest__.py | 2 +- .../models/project_milestone.py | 54 ++++++++++++------- 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/project_milestone_timeline_dynamic/__manifest__.py b/project_milestone_timeline_dynamic/__manifest__.py index fb005d25..6935a294 100644 --- a/project_milestone_timeline_dynamic/__manifest__.py +++ b/project_milestone_timeline_dynamic/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Project Milestone Timeline Dynamic", - "version": "1.0.0", + "version": "1.1.0", "author": "Numigi", "maintainer": "Numigi", "website": "https://bit.ly/numigi-com", diff --git a/project_milestone_timeline_dynamic/models/project_milestone.py b/project_milestone_timeline_dynamic/models/project_milestone.py index c335ad7a..c064d68f 100644 --- a/project_milestone_timeline_dynamic/models/project_milestone.py +++ b/project_milestone_timeline_dynamic/models/project_milestone.py @@ -8,44 +8,60 @@ class ProjectMilestone(models.Model): _inherit = "project.milestone" - @api.constrains('start_date') + @api.constrains("start_date") def _check_start_date_and_dependencies_end_date(self): for milestone in self: sorted_child_ids = milestone.child_ids.sorted( - key='target_date', reverse=True) - child_last_end_dates = milestone.child_ids.mapped('target_date') + key="target_date", reverse=True + ) + child_last_end_dates = milestone.child_ids.mapped("target_date") - if child_last_end_dates and milestone.start_date and \ - milestone.start_date < max(child_last_end_dates): + if ( + child_last_end_dates + and milestone.start_date + and milestone.start_date < max(child_last_end_dates) + ): raise ValidationError( - _('The milestone %s - %s is dependent on this ' - 'milestone and has a %s end date.' - ) % (sorted_child_ids[0].name, - sorted_child_ids[0].project_id.name, - fields.Date.to_string(max(child_last_end_dates))) + _( + "The milestone %s - %s is dependent on this " + "milestone and has a %s end date." + ) + % ( + sorted_child_ids[0].name, + sorted_child_ids[0].project_id.name, + fields.Date.to_string(max(child_last_end_dates)), + ) ) def _check_child_milestones_target_date(self): - child_last_end_dates = self.child_ids.mapped('target_date') - if child_last_end_dates and self.start_date and \ - self.start_date <= max(child_last_end_dates): + child_last_end_dates = self.child_ids.mapped("target_date") + if ( + child_last_end_dates + and self.start_date + and self.start_date <= max(child_last_end_dates) + ): milestone_duration = self.target_date - self.start_date self.start_date = max(child_last_end_dates) + timedelta(days=1) self.target_date = self.start_date + milestone_duration def _get_parent_milestone(self): self.env.cr.execute( - 'SELECT milestone_id FROM rel_project_milestone_dependencies ' - 'WHERE child_id = %s', (self.id,)) + "SELECT milestone_id FROM rel_project_milestone_dependencies " + "WHERE child_id = %s", + (self.id,), + ) milestone_id = self.env.cr.fetchone() - return self.env['project.milestone'].browse(milestone_id[0]) \ - if milestone_id else None + return ( + self.env["project.milestone"].browse(milestone_id[0]) + if milestone_id + else None + ) def write(self, vals): for milestone in self: - if 'child_ids' in vals: + if "child_ids" in vals: milestone._check_child_milestones_target_date() - if 'target_date' in vals: + if "target_date" in vals: parent_milestone = milestone._get_parent_milestone() if parent_milestone: parent_milestone._check_child_milestones_target_date() From 2425f67d6709bc3951c9e5037e0e2a0320612dd4 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Wed, 25 Feb 2026 17:09:40 +0000 Subject: [PATCH 5/5] [IMP] project_estimation_material --- project_estimation_material/__manifest__.py | 2 +- .../wizard/project_estimation_exit.py | 24 +++++++------------ .../models/project_milestone.py | 2 +- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/project_estimation_material/__manifest__.py b/project_estimation_material/__manifest__.py index f720abee..1a4f37c7 100644 --- a/project_estimation_material/__manifest__.py +++ b/project_estimation_material/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Project Estimation Material", - "version": "1.2.0", + "version": "1.3.0", "author": "Numigi", "maintainer": "Numigi", "license": "LGPL-3", diff --git a/project_estimation_material/wizard/project_estimation_exit.py b/project_estimation_material/wizard/project_estimation_exit.py index 38e85c91..48acfc26 100644 --- a/project_estimation_material/wizard/project_estimation_exit.py +++ b/project_estimation_material/wizard/project_estimation_exit.py @@ -2,9 +2,6 @@ # License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo import api, models, fields -import logging - -_logger = logging.getLogger(__name__) class ProjectEstimationExit(models.TransientModel): @@ -22,20 +19,15 @@ def _set_tasks(self): ) def validate(self): - _logger.info("Project Estimation Exit: Start validation") - ctx = dict(self.env.context) - auto_assign_config = self.env["ir.config_parameter"].sudo().get_param( - "stock_auto_assign_disabled.config", "off" - ) - if auto_assign_config == 'all': - ctx.update({ - 'stock_auto_assign_disable': True, # Force the auto assign disable - }) - res = super(ProjectEstimationExit, self.with_context(ctx)).validate() - self.with_context(ctx)._trigger_procurements() - return res + # Set the Context + self = self.with_context(disable_reservation=True, stock_auto_assign_disable=True) + super(ProjectEstimationExit, self).validate() + self._trigger_procurements() def _trigger_procurements(self): for line in self.project_id.material_line_ids: if line._should_generate_procurement(): - line._run_procurements() + line.with_context( + disable_reservation=True, + stock_auto_assign_disable=True + )._run_procurements() diff --git a/project_milestone_timeline_dynamic/models/project_milestone.py b/project_milestone_timeline_dynamic/models/project_milestone.py index c5e66542..ea372614 100644 --- a/project_milestone_timeline_dynamic/models/project_milestone.py +++ b/project_milestone_timeline_dynamic/models/project_milestone.py @@ -86,4 +86,4 @@ def update_parent_timeline(self, child_milestone, updated_val): child_last_end_dates.sort(reverse=True) self._assign_new_timeline( self.start_date, self.target_date, child_last_end_dates - ) \ No newline at end of file + )