Skip to content

Commit

Permalink
Merge pull request #7 from Numigi/TA#65341
Browse files Browse the repository at this point in the history
Ta#65341
  • Loading branch information
abenzbiria authored Jun 21, 2024
2 parents bda5b75 + 5a122f5 commit d88a0e8
Show file tree
Hide file tree
Showing 18 changed files with 357 additions and 0 deletions.
68 changes: 68 additions & 0 deletions project_milestone_time_kpi/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
Project Milestone time KPI
==========================

.. contents:: Table of Contents

Context
-------
The module has just enriched the milestones tab on the project, in order to offer 3 new fields:

* Total Estimated Hours.
* Total Hours Spent.
* Total Remaining Work.

This option is advantageous because it allows you to compare the total hours spent on the project with the estimated hours of each milestone in order to be able to weight an overrun on a batch phase, and to see the time remaining on the batch by also having visual status of milestones.

These fields are added to the list view of projects, in order to facilitate monitoring.


Overview
--------
The module inherits two modules that have been added to allow to define an estimated time on the milestone
`(project_milestone_estimated_hours)`, and to calculate the times spent on a milestone `(project_milestone_spent_hours)`

The module add 4 new fields to project:

* **Total Estimated Hours**: Field calculated by taking into account the total of the 'Estimated hours' fields of each milestone associated with the project.
* **Total Spent Hours**: Field calculated by taking into account the total of the 'Hours spent' fields of each milestone associated with the project.
* **Remaining Estimated Hours**: Calculated field based on the following calculation: Total Estimated Hours - Total Hours Spent.
* **Total Remaining Work**: Field calculated based on the total of the ‘Remaining hours’ fields of the tasks associated with a project.

**Total Estimated Hours**, **Total Spent Hours** and **Total Remaining Work** are visible under the milestone tab
in form view and visible in tree view after milestones column.

Usage
-----
As a user, from a project whose **Use milestones** box is checked, go to the tab of a project.

1. Add 2 milestones:

* Analysis (estimated 10h).

.. image:: project_milestone_time_kpi/static/description/milestone_1.png
:width: 100%
:align: center
:height: 600px
:alt: Milestone_1

* Realization (estimated 20h).

.. image:: project_milestone_time_kpi/static/description/milestone_2.png
:width: 100%
:align: center
:height: 600px
:alt: Milestone_2

2. From the project tasks, assigned to the respective milestones, add timelines.

.. image:: project_milestone_time_kpi/static/description/milestone_spent_hours.png
:width: 100%
:align: center
:height: 600px
:alt: Milestone_spent_hours

You can see that the estimated times of the milestones, and the times spent are well up in the list of milestones.

Contributors
------------
* Numigi (tm) and all its contributors (https://bit.ly/numigiens)
4 changes: 4 additions & 0 deletions project_milestone_time_kpi/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import models
17 changes: 17 additions & 0 deletions project_milestone_time_kpi/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{
"name": "Project Milestone Time KPI",
"version": "1.0.0",
"author": "Numigi",
"maintainer": "Numigi",
"website": "https://bit.ly/numigi-com",
"license": "LGPL-3",
"category": "Project",
"summary": "Track budgeted hours on projects using milestone",
"depends": ["project_milestone_estimated_hours",
"project_milestone_spent_hours"],
"data": ["views/project_project.xml"],
"installable": True,
}
42 changes: 42 additions & 0 deletions project_milestone_time_kpi/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * project_milestone_time_kpi
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-06-25 00:11+0000\n"
"PO-Revision-Date: 2022-06-25 00:11+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_milestone_time_kpi
#: model:ir.model,name:project_milestone_time_kpi.model_project_project
msgid "Project"
msgstr "Projet"

#. module: project_milestone_time_kpi
#: model:ir.model.fields,field_description:project_milestone_time_kpi.field_project_project__remaining_estimated_hours
msgid "Remaining Estimated Hours"
msgstr "Heures estimées restantes"

#. module: project_milestone_time_kpi
#: model:ir.model.fields,field_description:project_milestone_time_kpi.field_project_project__total_estimated_hours
msgid "Total Estimated Hours"
msgstr "Total heures estimés"

#. module: project_milestone_time_kpi
#: model:ir.model.fields,field_description:project_milestone_time_kpi.field_project_project__total_remaining_hours
msgid "Total Remaining Work"
msgstr "Total restant à faire"

#. module: project_milestone_time_kpi
#: model:ir.model.fields,field_description:project_milestone_time_kpi.field_project_project__total_spent_hours
msgid "Total Spent Hours"
msgstr "Total heures passées"

4 changes: 4 additions & 0 deletions project_milestone_time_kpi/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import project_project
43 changes: 43 additions & 0 deletions project_milestone_time_kpi/models/project_project.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# © 2023 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 fields, models, api


class Project(models.Model):
_inherit = "project.project"

total_estimated_hours = fields.Float(
"Total Estimated Hours", compute="_compute_total_hours", store=True
)
total_spent_hours = fields.Float(
"Total Spent Hours", compute="_compute_total_hours", store=True
)
remaining_estimated_hours = fields.Float(
"Remaining Estimated Hours",
compute="_compute_remaining_estimated_hours", store=True
)
total_remaining_hours = fields.Float(
"Total Remaining Work", compute="_compute_remaining_hours", store=True
)

@api.depends("milestone_ids", "milestone_ids.estimated_hours",
"milestone_ids.total_hours")
def _compute_total_hours(self):
for project in self:
project.total_estimated_hours = sum(
project.milestone_ids.mapped("estimated_hours"))
project.total_spent_hours = sum(
project.milestone_ids.mapped("total_hours"))

@api.depends("total_estimated_hours", "total_spent_hours")
def _compute_remaining_estimated_hours(self):
for project in self:
project.remaining_estimated_hours = \
project.total_estimated_hours - project.total_spent_hours

@api.depends("task_ids", "task_ids.remaining_hours")
def _compute_remaining_hours(self):
for project in self:
project.total_remaining_hours = sum(
project.task_ids.mapped("remaining_hours"))
22 changes: 22 additions & 0 deletions project_milestone_time_kpi/readme/CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## CONTEXT
The module has just enriched the milestones tab on the project, in order to offer 3 new fields:

Total Estimated Hours.
Total Hours Spent.
Total Remaining Work.

This option is advantageous because it allows you to compare the total hours spent on the project with the estimated hours of each milestone in order to be able to weight an overrun on a batch phase, and to see the time remaining on the batch by also having visual status of milestones.

These fields are added to the list view of projects, in order to facilitate monitoring.


## OVERVIEW
The module inherits two modules that have been added to allow to define an estimated time on the milestone (project_milestone_estimated_hours), and to calculate the times spent on a milestone (project_milestone_spent_hours)

The module add 4 new fields to project:

* **Total Estimated Hours**: Field calculated by taking into account the total of the 'Estimated hours' fields of each milestone associated with the project.
* **Total Spent Hours**: Field calculated by taking into account the total of the 'Hours spent' fields of each milestone associated with the project.
* **Remaining Estimated Hours**: Calculated field based on the following calculation: Total Estimated Hours - Total Hours Spent.
* **Total Remaining Work**: Field calculated based on the total of the ‘Remaining hours’ fields of the tasks associated with a project.
Total Estimated Hours, Total Spent Hours and Total Remaining Work are visible under the milestone tab in form view and visible in tree view after milestones column.
1 change: 1 addition & 0 deletions project_milestone_time_kpi/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Numigi (tm) and all its contributors (https://bit.ly/numigiens)
5 changes: 5 additions & 0 deletions project_milestone_time_kpi/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The module enriched the milestones tab on the project, in order to offer 3 new fields:

Total Estimated Hours.
Total Hours Spent.
Total Remaining Work.
1 change: 1 addition & 0 deletions project_milestone_time_kpi/readme/ROADMAP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Allow the user the to analyse estimated, spent and remaining hours by project
17 changes: 17 additions & 0 deletions project_milestone_time_kpi/readme/USAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Usage
As a user, from a project whose **Use milestones** box is checked, go to the tab of a project.

1. Add 2 milestones:
* Analysis (estimated 10h)

![alt text](../static/description/milestone_1.png)

* Realization (estimated 20h).

![alt text](../static/description/milestone_2.png)

2. From the project tasks, assigned to the respective milestones, add timelines.

![alt text](../static/description/milestone_spent_hours.png)
You can see that the estimated times of the milestones, and the times spent are well up in the list of milestones.

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_milestone_time_kpi/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import test_project_milestone_time_kpi
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# © 2023 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


class TestProjectMilestoneTimeKPI(SavepointCase):

@classmethod
def setUpClass(cls):
super(TestProjectMilestoneTimeKPI, cls).setUpClass()

# create a generic Project with 2 milestones and 2 tasks associated to milestones
cls.stage = cls.env["project.task.type"].create({
"name": "New"
})

cls.project_a = cls.env["project.project"].create({
"name": "Project A",
"use_milestones": True,
})

cls.milestone_a = cls.env['project.milestone'].create({
"name": "Analysis",
"estimated_hours": 8,
"project_id": cls.project_a.id,
})
cls.milestone_b = cls.env['project.milestone'].create({
"name": "Realization",
"estimated_hours": 20,
"project_id": cls.project_a.id,
})

cls.task_a = cls.env["project.task"].create({
"name": "Task A",
"project_id": cls.project_a.id,
"milestone_id": cls.milestone_a.id,
"planned_hours": 4,
"stage_id": cls.stage.id,
})

cls.task_b = cls.env["project.task"].create({
"name": "Task B",
"project_id": cls.project_a.id,
"milestone_id": cls.milestone_b.id,
"planned_hours": 8,
"stage_id": cls.stage.id,
})

# Add timelines to created tasks
cls.timesheet_a = cls.env["account.analytic.line"].create({
"name": "Analyse",
"project_id": cls.project_a.id,
"task_id": cls.task_a.id,
"unit_amount": 3,
"employee_id": 1,
"date": "2022-06-25",
})

cls.timesheet_b = cls.env["account.analytic.line"].create({
"name": "Conception",
"project_id": cls.project_a.id,
"task_id": cls.task_b.id,
"unit_amount": 4,
"employee_id": 1,
"date": "2022-06-30",
})

def test_timesheet_line_created(self):
""" Test total_remaining_hours calculation after adding a new timeline to task """
self.env["account.analytic.line"].create({
"name": "Development",
"project_id": self.project_a.id,
"task_id": self.task_b.id,
"unit_amount": 3,
"employee_id": 1,
"date": "2022-06-30",
})
assert self.project_a.total_estimated_hours == 28
assert self.project_a.total_spent_hours == 10
assert self.project_a.total_remaining_hours == 2

def test_add_milestone(self):
self.env['project.milestone'].create({
"name": "Test",
"estimated_hours": 8,
"project_id": self.project_a.id,
})
assert self.project_a.total_estimated_hours == 36

def test_unlink_milestone(self):
self.milestone_b.unlink()
assert self.project_a.total_estimated_hours == 8
assert self.project_a.total_spent_hours == 3

def test_update_milestone(self):
self.milestone_a.write({"estimated_hours": 10})
assert self.project_a.total_estimated_hours == 30
31 changes: 31 additions & 0 deletions project_milestone_time_kpi/views/project_project.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="project_form" model="ir.ui.view">
<field name="name">Project: add milestone time kpi</field>
<field name="model">project.project</field>
<field name="inherit_id" ref="project_milestone.project_enhancement_milestone_view_inherit_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='milestone_ids']" position="inside">
<group name="milestone_time_kpi" class="oe_subtotal_footer oe_right" colspan="2">
<field name="total_estimated_hours" widget="float_time"/>
<field name="total_spent_hours" widget="float_time"/>
<field name="remaining_estimated_hours" widget="float_time"/>
<field name="total_remaining_hours" widget="float_time"/>
</group>
</xpath>
</field>
</record>

<record id="project_list" model="ir.ui.view">
<field name="name">Project: add milestone time kpi</field>
<field name="model">project.project</field>
<field name="inherit_id" ref="project_milestone.project_milestone_view_inherit_list"/>
<field name="arch" type="xml">
<field name="milestone_ids" position="after">
<field name="total_estimated_hours" widget="float_time"/>
<field name="total_spent_hours" widget="float_time"/>
<field name="total_remaining_hours" widget="float_time"/>
</field>
</field>
</record>
</odoo>

0 comments on commit d88a0e8

Please sign in to comment.