-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MIG][16.0] project_progree_variance
- Loading branch information
Showing
18 changed files
with
331 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Project Progress Variance | ||
========================= | ||
This module allows to: | ||
|
||
* Add the ”Variance on progress” field in the form view of a task | ||
Computed as : task real progress + task theorical progress. | ||
|
||
.. image:: static/description/task_progress_variance.png | ||
|
||
* Add the “Variance on progress” in the analysis list view “Progress of tasks” | ||
|
||
.. image:: static/description/task_progress_report.png | ||
|
||
* Add the ”Progress” tab in the form view of a project | ||
* The “Total theoretical progress” field | ||
Computed as : total of effective hours of project tasks / total of planned hours of project tasks. | ||
|
||
* The "Total real progress" field | ||
Computed as : total of effective hours of project tasks / total of projected hours of project tasks. | ||
|
||
* The “Total variance on progress” field | ||
Computed as : total of real progress - Total theoretical progress. | ||
|
||
.. image:: static/description/project_progress_tab.png | ||
|
||
Contributors | ||
------------ | ||
* Numigi (tm) and all its contributors (https://bit.ly/numigiens) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import models | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
{ | ||
"name": "Project Progress Variance", | ||
"version": "16.0.1.0.0", | ||
"author": "Numigi", | ||
"maintainer": "Numigi", | ||
"website": "https://bit.ly/numigi-com", | ||
"license": "AGPL-3", | ||
"category": "Project", | ||
"depends": ["project_projected_hours"], | ||
"summary": "Add some progress variance time on task and project", | ||
"data": [ | ||
"views/project_project_views.xml", | ||
"views/project_task_views.xml", | ||
"views/project_task_progress_report_views.xml", | ||
], | ||
"installable": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Translation of Odoo Server. | ||
# This file contains the translation of the following modules: | ||
# * project_progress_variance | ||
# | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: Odoo Server 16.0\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2024-12-06 06:10+0000\n" | ||
"PO-Revision-Date: 2024-12-06 06:10+0000\n" | ||
"Last-Translator: \n" | ||
"Language-Team: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: \n" | ||
"Plural-Forms: \n" | ||
|
||
#. module: project_progress_variance | ||
#: model_terms:ir.ui.view,arch_db:project_progress_variance.edit_project | ||
msgid "Progress" | ||
msgstr "Avancement" | ||
|
||
#. module: project_progress_variance | ||
#: model:ir.model.fields,field_description:project_progress_variance.field_project_task__progress_variance | ||
msgid "Progress Variance" | ||
msgstr "Écart sur avancement" | ||
|
||
#. module: project_progress_variance | ||
#: model:ir.model,name:project_progress_variance.model_project_project | ||
msgid "Project" | ||
msgstr "Projet" | ||
|
||
#. module: project_progress_variance | ||
#: model:ir.model,name:project_progress_variance.model_project_task | ||
msgid "Task" | ||
msgstr "Tâche" | ||
|
||
#. module: project_progress_variance | ||
#: model:ir.model.fields,field_description:project_progress_variance.field_project_project__total_progress | ||
msgid "Total Progress" | ||
msgstr "Total avancement théorique" | ||
|
||
#. module: project_progress_variance | ||
#: model:ir.model.fields,field_description:project_progress_variance.field_project_project__total_progress_variance | ||
msgid "Total Progress Variance" | ||
msgstr "Total écart sur avancement" | ||
|
||
#. module: project_progress_variance | ||
#: model:ir.model.fields,field_description:project_progress_variance.field_project_project__total_real_progress | ||
msgid "Total Real Progress" | ||
msgstr "Total avancement réel" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import project_project | ||
from . import project_task | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import api, fields, models | ||
|
||
|
||
class ProjectProject(models.Model): | ||
_inherit = "project.project" | ||
|
||
total_progress = fields.Float( | ||
"Total Progress", | ||
digits=(16, 2), | ||
compute="_compute_total_progress", | ||
readonly=True, | ||
store=True, | ||
) | ||
|
||
total_real_progress = fields.Float( | ||
"Total Real Progress", | ||
digits=(16, 2), | ||
compute="_compute_total_real_progress", | ||
readonly=True, | ||
store=True, | ||
) | ||
|
||
total_progress_variance = fields.Float( | ||
"Total Progress Variance", | ||
digits=(16, 2), | ||
compute="_compute_total_progress_variance", | ||
readonly=True, | ||
store=True, | ||
) | ||
|
||
@api.depends("tasks", "tasks.planned_hours", "tasks.effective_hours") | ||
def _compute_total_progress(self): | ||
for project in self: | ||
planned_hours = sum(project.tasks.mapped("planned_hours")) | ||
effective_hours = sum(project.tasks.mapped("effective_hours")) | ||
project.total_progress = ( | ||
100.0 * (effective_hours / planned_hours) if planned_hours else 0.0 | ||
) | ||
|
||
@api.depends("tasks", "tasks.projected_hours", "tasks.effective_hours") | ||
def _compute_total_real_progress(self): | ||
for project in self: | ||
projected_hours = sum(project.tasks.mapped("projected_hours")) | ||
effective_hours = sum(project.tasks.mapped("effective_hours")) | ||
project.total_real_progress = ( | ||
100.0 * (effective_hours / projected_hours) if projected_hours else 0.0 | ||
) | ||
|
||
@api.depends("total_progress", "total_real_progress") | ||
def _compute_total_progress_variance(self): | ||
for project in self: | ||
project.total_progress_variance = ( | ||
project.total_real_progress - project.total_progress | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import api, fields, models | ||
|
||
|
||
class ProjectTask(models.Model): | ||
_inherit = "project.task" | ||
|
||
progress_variance = fields.Float( | ||
"Progress Variance", | ||
digits=(16, 2), | ||
compute="_compute_progress_variance", | ||
readonly=True, | ||
store=True, | ||
) | ||
|
||
@api.depends("progress", "real_progress") | ||
def _compute_progress_variance(self): | ||
for task in self: | ||
task.progress_variance = task.real_progress - task.progress |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+114 KB
project_progress_variance/static/description/task_progress_variance.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import test_progress_variance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens) | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from datetime import datetime | ||
|
||
from odoo.tests.common import TransactionCase | ||
|
||
|
||
class TestCustomerReference(TransactionCase): | ||
@classmethod | ||
def setUpClass(cls): | ||
super().setUpClass() | ||
cls.project = cls.env["project.project"].create( | ||
{"name": "test_project", "allow_timesheets": True} | ||
) | ||
cls.task_1 = cls.env["project.task"].create( | ||
{"name": "test_task_1", "project_id": cls.project.id} | ||
) | ||
|
||
cls.task_2 = cls.env["project.task"].create( | ||
{"name": "test_task_2", "project_id": cls.project.id} | ||
) | ||
|
||
def test_total_progress(self): | ||
self.assertEqual(self.project.total_progress, 0) | ||
self._load_analytic_line_remaining_hours_not_updated() | ||
self.assertEqual(round(self.project.total_progress, 2), 47.83) | ||
|
||
def test_total_progress_remaining_hours_updated(self): | ||
self.assertEqual(self.project.total_progress, 0) | ||
self._load_analytic_line_with_remaining_hours_updated() | ||
self.assertEqual(round(self.project.total_progress, 2), 32.5) | ||
|
||
def test_total_real_progress(self): | ||
self.assertEqual(self.project.total_real_progress, 0) | ||
self._load_analytic_line_remaining_hours_not_updated() | ||
self.assertEqual(round(self.project.total_real_progress, 2), 47.83) | ||
|
||
def test_total_real_progress_remaining_hours_updated(self): | ||
self.assertEqual(self.project.total_real_progress, 0) | ||
self._load_analytic_line_with_remaining_hours_updated() | ||
self.assertEqual(round(self.project.total_real_progress, 2), 27.08) | ||
|
||
def test_total_progress_variance(self): | ||
self.assertEqual(self.project.total_progress_variance, 0) | ||
self._load_analytic_line_remaining_hours_not_updated() | ||
self.assertEqual(self.project.total_progress_variance, 0) | ||
|
||
def test_total_progress_variance_remaining_hours_updated(self): | ||
self.assertEqual(self.project.total_progress_variance, 0) | ||
self._load_analytic_line_with_remaining_hours_updated() | ||
self.assertEqual(round(self.project.total_real_progress, 2), 27.08) | ||
self.assertEqual(round(self.project.total_progress, 2), 32.5) | ||
self.assertEqual(round(self.project.total_progress_variance, 2), -5.42) | ||
|
||
def _load_analytic_line_remaining_hours_not_updated(self): | ||
self.task_1.planned_hours = 10 | ||
self.task_2.planned_hours = 13 | ||
self._create_analytic_line( | ||
datetime(2023, 3, 24, 3), tz="EST", task_id=self.task_1, unit_amount=7 | ||
) | ||
self._create_analytic_line( | ||
datetime(2023, 3, 24, 3), tz="EST", task_id=self.task_2, unit_amount=4 | ||
) | ||
|
||
def _load_analytic_line_with_remaining_hours_updated(self): | ||
self.task_1.planned_hours = 30 | ||
self.task_2.planned_hours = 10 | ||
self._create_analytic_line( | ||
datetime(2023, 3, 24, 3), tz="EST", task_id=self.task_1, unit_amount=5 | ||
) | ||
self._create_analytic_line( | ||
datetime(2023, 3, 24, 3), tz="EST", task_id=self.task_2, unit_amount=8 | ||
) | ||
self.task_1.remaining_hours = 30 | ||
self.task_2.remaining_hours = 5 | ||
|
||
def _create_analytic_line(self, datetime_, tz=None, task_id=False, unit_amount=0): | ||
self.env["account.analytic.line"].with_context(tz=tz).create( | ||
{ | ||
"date": datetime_, | ||
"project_id": self.project.id, | ||
"task_id": task_id.id, | ||
"name": "Test line", | ||
"unit_amount": unit_amount, | ||
"employee_id": self.ref("hr.employee_admin"), | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?xml version='1.0' encoding='UTF-8'?> | ||
<odoo> | ||
|
||
<record id="edit_project" model="ir.ui.view"> | ||
<field name="name">project.project.form.inherit</field> | ||
<field name="model">project.project</field> | ||
<field name="inherit_id" ref="project.edit_project"/> | ||
<field name="arch" type="xml"> | ||
<xpath expr="//page[@name='settings']" position="after"> | ||
<page name="project_progress" string="Progress" groups="project.group_project_manager"> | ||
<group> | ||
<field name="total_progress" widget="progressbar"/> | ||
<field name="total_real_progress" widget="progressbar"/> | ||
<field name="total_progress_variance" widget="progressbar"/> | ||
</group> | ||
</page> | ||
</xpath> | ||
</field> | ||
</record> | ||
|
||
</odoo> |
15 changes: 15 additions & 0 deletions
15
project_progress_variance/views/project_task_progress_report_views.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?xml version='1.0' encoding='UTF-8'?> | ||
<odoo> | ||
|
||
<record model="ir.ui.view" id="view_task_project_progress_tree"> | ||
<field name="name">report.project.task.progress.tree.inherited</field> | ||
<field name="model">project.task</field> | ||
<field name="inherit_id" ref="project_projected_hours.view_task_project_progress_tree" /> | ||
<field name="arch" type="xml"> | ||
<field name="real_progress" position="after"> | ||
<field name="progress_variance" groups="hr_timesheet.group_hr_timesheet_user"/> | ||
</field> | ||
</field> | ||
</record> | ||
|
||
</odoo> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?xml version='1.0' encoding='UTF-8'?> | ||
<odoo> | ||
|
||
<record model="ir.ui.view" id="view_task_form2_inherited"> | ||
<field name="name">project.task.form.inherited</field> | ||
<field name="model">project.task</field> | ||
<field name="inherit_id" ref="project_projected_hours.view_task_form2_inherited" /> | ||
<field name="arch" type="xml"> | ||
<field name="real_progress" position="after"> | ||
<field name="progress_variance" widget="progressbar" groups="hr_timesheet.group_hr_timesheet_user"/> | ||
</field> | ||
</field> | ||
</record> | ||
|
||
</odoo> |