diff --git a/project_milestone_enhanced/__manifest__.py b/project_milestone_enhanced/__manifest__.py
index 36ba567f..db6730ec 100644
--- a/project_milestone_enhanced/__manifest__.py
+++ b/project_milestone_enhanced/__manifest__.py
@@ -13,6 +13,7 @@
"data": [
"views/project_milestone.xml",
"views/project.xml",
+ "views/task_stage.xml",
],
"installable": True,
}
diff --git a/project_milestone_enhanced/i18n/fr.po b/project_milestone_enhanced/i18n/fr.po
index 71b4bda8..7fbfb7da 100644
--- a/project_milestone_enhanced/i18n/fr.po
+++ b/project_milestone_enhanced/i18n/fr.po
@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2024-12-03 06:25+0000\n"
-"PO-Revision-Date: 2024-12-03 06:25+0000\n"
+"POT-Creation-Date: 2024-12-04 15:24+0000\n"
+"PO-Revision-Date: 2024-12-04 15:24+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -15,10 +15,40 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_needaction
+msgid "Action Needed"
+msgstr "Nécessite une action"
+
#. module: project_milestone_enhanced
#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__active
msgid "Active"
-msgstr "Actif"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_ids
+msgid "Activities"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_exception_decoration
+msgid "Activity Exception Decoration"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_state
+msgid "Activity State"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_type_icon
+msgid "Activity Type Icon"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.ui.menu,name:project_milestone_enhanced.milestone_configuration_menu
+msgid "All Milestones"
+msgstr "Tous les jalons"
#. module: project_milestone_enhanced
#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_active_view_form
@@ -34,13 +64,140 @@ msgid ""
msgstr ""
"Archiver un projet archivera automatiquement ses tâches et jalons. Voulez-vous continuer ?"
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_attachment_count
+msgid "Attachment Count"
+msgstr "Nombre de pièces jointes"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_task_type__closed
+msgid "Closed"
+msgstr "Clôturé"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_follower_ids
+msgid "Followers"
+msgstr "Abonnés"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_partner_ids
+msgid "Followers (Partners)"
+msgstr "Abonnés (Partenaires)"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__activity_type_icon
+msgid "Font awesome icon e.g. fa-tasks"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_milestone_view_search
+msgid "Group By"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__has_message
+msgid "Has Message"
+msgstr "A un message"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_exception_icon
+msgid "Icon"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__activity_exception_icon
+msgid "Icon to indicate an exception activity."
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__message_needaction
+msgid "If checked, new messages require your attention."
+msgstr "Si coché, de nouveaux messages demandent votre attention."
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__message_has_error
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__message_has_sms_error
+msgid "If checked, some messages have a delivery error."
+msgstr "Si coché, certains messages ont une erreur de livraison."
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_is_follower
+msgid "Is Follower"
+msgstr "Est un abonné"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_main_attachment_id
+msgid "Main Attachment"
+msgstr "Pièce jointe principale"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_has_error
+msgid "Message Delivery error"
+msgstr "Erreur d'envoi du message"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_ids
+msgid "Messages"
+msgstr ""
+
#. module: project_milestone_enhanced
#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_active_view_form
msgid "Milestones"
msgstr "Jalons"
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__my_activity_date_deadline
+msgid "My Activity Deadline"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_date_deadline
+msgid "Next Activity Deadline"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_summary
+msgid "Next Activity Summary"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_type_id
+msgid "Next Activity Type"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_needaction_counter
+msgid "Number of Actions"
+msgstr "Nombre d'actions"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_has_error_counter
+msgid "Number of errors"
+msgstr "Nombre d'erreurs"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__message_needaction_counter
+msgid "Number of messages requiring action"
+msgstr "Nombre de messages nécessitant une action"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__message_has_error_counter
+msgid "Number of messages with delivery error"
+msgstr "Nombre de messages avec des erreurs d'envoi"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__progress
+msgid "Percentage of Completed Tasks vs Incomplete Tasks."
+msgstr "Pourcentage de tâches achevées par rapport aux tâches incomplètes."
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__progress
+msgid "Progress"
+msgstr "Progression"
+
#. module: project_milestone_enhanced
#: model:ir.model,name:project_milestone_enhanced.model_project_project
+#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_milestone_view_search
msgid "Project"
msgstr "Projet"
@@ -49,21 +206,68 @@ msgstr "Projet"
msgid "Project Milestone"
msgstr "Jalon du projet"
+#. module: project_milestone_enhanced
+#: model:ir.actions.act_window,name:project_milestone_enhanced.project_milestone_action
+msgid "Project Milestones"
+msgstr "Jalons du projet"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__activity_user_id
+msgid "Responsible User"
+msgstr ""
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__message_has_sms_error
+msgid "SMS Delivery error"
+msgstr "Erreur d'envoi SMS"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__sequence
+msgid "Sequence"
+msgstr "Séquence"
+
#. module: project_milestone_enhanced
#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_project__show_milestones
msgid "Show milestones"
msgstr "Afficher les jalons"
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__activity_state
+msgid ""
+"Status based on activities\n"
+"Overdue: Due date is already passed\n"
+"Today: Activity date is today\n"
+"Planned: Future activities."
+msgstr "Statut basé sur les activités\n"
+"En retard : la date d'échéance est déjà dépassée\n"
+"Aujourd'hui : la date de l'activité est aujourd'hui\n"
+"Planifié : activités futures."
+
+#. module: project_milestone_enhanced
+#: model:ir.model,name:project_milestone_enhanced.model_project_task_type
+msgid "Task Stage"
+msgstr "Étape de tâche"
+
#. module: project_milestone_enhanced
#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_milestone_active_view_form
msgid "Tasks"
msgstr "Tâches"
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_task_type__closed
+msgid "Tasks in this stage are considered closed."
+msgstr "Les tâches dans cette étape sont considérées comme clôturées."
+
#. module: project_milestone_enhanced
#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__active_toggle
msgid "Toggle active"
msgstr "Toggle actif"
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__activity_exception_decoration
+msgid "Type of the exception activity on record."
+msgstr "Type d'activité d'exception enregistrée."
+
#. module: project_milestone_enhanced
#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_active_view_form
#: model_terms:ir.ui.view,arch_db:project_milestone_enhanced.project_milestone_active_view_form
@@ -76,4 +280,14 @@ msgid ""
"Unarchiving a project automatically unarchives its tasks and milestones. Do "
"you want to proceed ?"
msgstr ""
-""Désarchiver un projet désarchivera automatiquement ses tâches et jalons. Voulez-vous continuer ?"
\ No newline at end of file
+""Désarchiver un projet désarchivera automatiquement ses tâches et jalons. Voulez-vous continuer ?"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,field_description:project_milestone_enhanced.field_project_milestone__website_message_ids
+msgid "Website Messages"
+msgstr "Messages du site web"
+
+#. module: project_milestone_enhanced
+#: model:ir.model.fields,help:project_milestone_enhanced.field_project_milestone__website_message_ids
+msgid "Website communication history"
+msgstr "Historique de communication du site web"
\ No newline at end of file
diff --git a/project_milestone_enhanced/models/__init__.py b/project_milestone_enhanced/models/__init__.py
index eb62378e..5b19a8c4 100644
--- a/project_milestone_enhanced/models/__init__.py
+++ b/project_milestone_enhanced/models/__init__.py
@@ -3,3 +3,4 @@
from . import project
from . import project_milestone
+from . import task_stage
diff --git a/project_milestone_enhanced/models/project_milestone.py b/project_milestone_enhanced/models/project_milestone.py
index 2a894745..c618903a 100644
--- a/project_milestone_enhanced/models/project_milestone.py
+++ b/project_milestone_enhanced/models/project_milestone.py
@@ -1,14 +1,22 @@
# Copyright 2023 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
-from odoo import models, fields
+from odoo import api, models, fields
class ProjectMilestone(models.Model):
- _inherit = "project.milestone"
+ _name = "project.milestone"
+
+ _inherit = ['project.milestone', 'mail.thread', 'mail.activity.mixin']
active = fields.Boolean(string="Active", default=True)
active_toggle = fields.Boolean(string="Toggle active", default=True)
+ sequence = fields.Integer()
+ progress = fields.Float(
+ compute="_compute_milestone_progress",
+ store=True,
+ help="Percentage of Completed Tasks vs Incomplete Tasks.",
+ )
def toggle_active(self):
res = super(ProjectMilestone, self).toggle_active()
@@ -38,3 +46,17 @@ def _milestone_not_active(self):
self.filtered(lambda milestone: not milestone.active_toggle).write(
{"active": False}
)
+
+ @api.depends('task_ids.stage_id')
+ def _compute_milestone_progress(self):
+ total_tasks_count = 0.0
+ closed_tasks_count = 0.0
+ for record in self:
+ for task_record in record.task_ids:
+ total_tasks_count += 1
+ if task_record.stage_id.closed:
+ closed_tasks_count += 1
+ if total_tasks_count > 0:
+ record.progress = (closed_tasks_count / total_tasks_count) * 100
+ else:
+ record.progress = 0.0
diff --git a/project_milestone_enhanced/models/task_stage.py b/project_milestone_enhanced/models/task_stage.py
new file mode 100644
index 00000000..6f5f804d
--- /dev/null
+++ b/project_milestone_enhanced/models/task_stage.py
@@ -0,0 +1,13 @@
+# Copyright 2023 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens)
+# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
+
+from odoo import models, fields
+
+
+class ProjectTaskType(models.Model):
+ _inherit = 'project.task.type'
+
+ closed = fields.Boolean(
+ help="Tasks in this stage are considered closed.",
+ default=False,
+ )
diff --git a/project_milestone_enhanced/tests/test_project.py b/project_milestone_enhanced/tests/test_project.py
index f172a8ca..1c9951f2 100644
--- a/project_milestone_enhanced/tests/test_project.py
+++ b/project_milestone_enhanced/tests/test_project.py
@@ -1,42 +1,56 @@
# Copyright 2023 - today Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).
-from odoo.tests.common import SavepointCase
+from odoo.tests import common
-class TestProject(SavepointCase):
- @classmethod
- def setUpClass(cls):
- super().setUpClass()
- cls.project = cls.env["project.project"].create(
+class TestProject(common.TransactionCase):
+ def setUp(self):
+ super().setUp()
+ self.project = self.env["project.project"].create(
{"name": "My Project", "allow_milestones": True}
)
- cls.milestone = cls.env["project.milestone"].create(
- {"name": "My Milestone", "project_id": cls.project.id}
+ self.milestone = self.env["project.milestone"].create(
+ {"name": "My Milestone", "project_id": self.project.id}
)
- cls.milestone_2 = cls.env["project.milestone"].create(
- {"name": "My Milestone 2", "project_id": cls.project.id}
+ self.milestone_2 = self.env["project.milestone"].create(
+ {"name": "My Milestone 2", "project_id": self.project.id}
)
- cls.task = cls.env["project.task"].create(
+ self.task = self.env["project.task"].create(
{
"name": "My Task",
- "project_id": cls.project.id,
- "milestone_id": cls.milestone.id,
+ "project_id": self.project.id,
+ "milestone_id": self.milestone.id,
}
)
- cls.task_2 = cls.env["project.task"].create(
+ self.task_2 = self.env["project.task"].create(
{
"name": "My Task 1",
- "project_id": cls.project.id,
- "milestone_id": cls.milestone.id,
+ "project_id": self.project.id,
+ "milestone_id": self.milestone.id,
"active": False,
}
)
+ self.task_3 = self.env["project.task"].create(
+ {
+ "name": "My Task 2",
+ "project_id": self.project.id,
+ "milestone_id": self.milestone.id,
+ }
+ )
+
+ self.test_open_stage = self.env['project.task.type'].create(
+ {'name': 'TestOpenStage'}
+ )
+ self.test_close_stage = self.env['project.task.type'].create(
+ {'name': 'TestCloseStage', 'closed': True}
+ )
+
def test_copy_project(self):
project = self.project.copy({})
tasks = project.with_context(active_test=False).task_ids
@@ -69,3 +83,12 @@ def test_project_change_active(self):
self.project.toggle_active()
assert self.milestone.active
assert not self.milestone_2.active
+
+ def test_milestone_progress(self):
+ milestone1 = self.milestone
+
+ self.task.stage_id = self.test_close_stage.id
+ self.assertEqual(milestone1.progress, 50)
+
+ self.task_3.stage_id = self.test_close_stage.id
+ self.assertEqual(milestone1.progress, 100)
diff --git a/project_milestone_enhanced/views/project.xml b/project_milestone_enhanced/views/project.xml
index 1f328614..b0e21a3c 100644
--- a/project_milestone_enhanced/views/project.xml
+++ b/project_milestone_enhanced/views/project.xml
@@ -28,6 +28,7 @@
+
diff --git a/project_milestone_enhanced/views/project_milestone.xml b/project_milestone_enhanced/views/project_milestone.xml
index 5b257807..25a2aa7e 100644
--- a/project_milestone_enhanced/views/project_milestone.xml
+++ b/project_milestone_enhanced/views/project_milestone.xml
@@ -27,6 +27,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Project Milestone Sequence
+ project.milestone
+ 0
+ 1
+
+
+
+
+ Project Milestone List
+ project.milestone
+
+
+
+
+
+
+
+
+
+
+
+
+ Project Milestone Search
+ project.milestone
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Project Milestones
+ project.milestone
+ {'group_by': 'project_id'}
+ tree,form
+
+
+
+
diff --git a/project_milestone_enhanced/views/task_stage.xml b/project_milestone_enhanced/views/task_stage.xml
new file mode 100644
index 00000000..ed4cefa7
--- /dev/null
+++ b/project_milestone_enhanced/views/task_stage.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ project.task.type
+
+
+
+
+
+
+
+
+