Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ta#72177 [MIG][16.0] project_progree_variance #472

Open
wants to merge 1 commit into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .docker_files/main/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"project_task_full_text_search",
"project_type_advanced",
"project_default_task_stage",
"project_progress_variance",
"project_stage_allow_timesheet",
],
"installable": True,
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ COPY project_stage_allow_timesheet mnt/extra-addons/project_stage_allow_timeshee
COPY project_task_date_planned /mnt/extra-addons/project_task_date_planned
COPY project_task_full_text_search /mnt/extra-addons/project_task_full_text_search
COPY project_type_advanced /mnt/extra-addons/project_type_advanced
COPY project_progress_variance /mnt/extra-addons/project_progress_variance
COPY project_default_task_stage /mnt/extra-addons/project_default_task_stage


Expand Down
28 changes: 28 additions & 0 deletions project_progress_variance/README.rst
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)
4 changes: 4 additions & 0 deletions project_progress_variance/__init__.py
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

Check notice on line 4 in project_progress_variance/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_progress_variance/__init__.py#L4

'.models' imported but unused (F401)
20 changes: 20 additions & 0 deletions project_progress_variance/__manifest__.py
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).

{

Check warning on line 4 in project_progress_variance/__manifest__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_progress_variance/__manifest__.py#L4

Statement seems to have no effect
"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,
}
51 changes: 51 additions & 0 deletions project_progress_variance/i18n/fr.po
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"
5 changes: 5 additions & 0 deletions project_progress_variance/models/__init__.py
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

Check notice on line 4 in project_progress_variance/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_progress_variance/models/__init__.py#L4

'.project_project' imported but unused (F401)
from . import project_task

Check notice on line 5 in project_progress_variance/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_progress_variance/models/__init__.py#L5

'.project_task' imported but unused (F401)
57 changes: 57 additions & 0 deletions project_progress_variance/models/project_project.py
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
)
21 changes: 21 additions & 0 deletions project_progress_variance/models/project_task.py
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions project_progress_variance/tests/__init__.py
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
88 changes: 88 additions & 0 deletions project_progress_variance/tests/test_progress_variance.py
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"),
}
)
21 changes: 21 additions & 0 deletions project_progress_variance/views/project_project_views.xml
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>
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>
15 changes: 15 additions & 0 deletions project_progress_variance/views/project_task_views.xml
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>
Loading