From c0ba518e63e2863e251ea3cc385fdf81246692ee Mon Sep 17 00:00:00 2001 From: Abdellatif BENZBIRIA Date: Tue, 18 Mar 2025 22:51:54 +0000 Subject: [PATCH 1/6] 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/6] 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/6] 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/6] 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 47d3595b90533a80229e1bc6611bb8f9351e72b9 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 23 Mar 2026 10:23:18 +0000 Subject: [PATCH 5/6] TA#83593 [IMP] meeting_minuets_project_sterring : order by seuqence steering ids --- meeting_minutes_project_steering/__manifest__.py | 2 +- .../models/project_steering_kpi_line.py | 6 ++++++ .../views/meeting_minutes_views.xml | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/meeting_minutes_project_steering/__manifest__.py b/meeting_minutes_project_steering/__manifest__.py index f480d020..59e71eca 100644 --- a/meeting_minutes_project_steering/__manifest__.py +++ b/meeting_minutes_project_steering/__manifest__.py @@ -3,7 +3,7 @@ { "name": "Meeting Minutes Project Steering", - "version": "1.0.2", + "version": "1.0.3", "author": "Numigi", "maintainer": "Numigi", "website": "https://bit.ly/numigi-com", diff --git a/meeting_minutes_project_steering/models/project_steering_kpi_line.py b/meeting_minutes_project_steering/models/project_steering_kpi_line.py index e90e016a..95d75060 100644 --- a/meeting_minutes_project_steering/models/project_steering_kpi_line.py +++ b/meeting_minutes_project_steering/models/project_steering_kpi_line.py @@ -7,6 +7,7 @@ class ProjectSteeringKpiLine(models.Model): _name = "project.steering.kpi.line" _description = "Project Steering KPI Line" + _order = "sequence, id" name = fields.Char(string="Name") meeting_minutes_id = fields.Many2one( @@ -27,3 +28,8 @@ class ProjectSteeringKpiLine(models.Model): related="task_id.date_deadline", string="Task Deadline" ) notes = fields.Text(string="Notes") + _order = "sequence, id" + sequence = fields.Integer( + string="Sequence", + default=10, + ) diff --git a/meeting_minutes_project_steering/views/meeting_minutes_views.xml b/meeting_minutes_project_steering/views/meeting_minutes_views.xml index 574e8cc9..4d95bc86 100644 --- a/meeting_minutes_project_steering/views/meeting_minutes_views.xml +++ b/meeting_minutes_project_steering/views/meeting_minutes_views.xml @@ -24,6 +24,7 @@ + From dee53bf201def48a5b559a276479aa2d10dac9c3 Mon Sep 17 00:00:00 2001 From: Abdellatif Benzbiria Date: Mon, 23 Mar 2026 10:34:32 +0000 Subject: [PATCH 6/6] TA#83593 pre-commit --- project_milestone_timeline_dynamic/models/project_milestone.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 + )