forked from OCA/business-requirement
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[8.0][ADD] Added Earned Value Management Report (OCA#107)
- Loading branch information
1 parent
0894252
commit 08f21c9
Showing
7 changed files
with
411 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
|
||
|
||
=============================== | ||
Earned Value Management Report | ||
=============================== | ||
|
||
Introduction | ||
============ | ||
|
||
This module is part of a set of modules (`Business Requirements <https://github.com/OCA/business-requirement/blob/8.0/README.md>`_). | ||
|
||
|
||
This module introduces **Earned Value Management report** based on the information | ||
from the Business Requirements Resources and Deliverable lines. You can check the | ||
following resources for more information about EVM: | ||
|
||
* `[RFC] Earned Value Management Report <https://github.com/OCA/business-requirement/issues/81>`_ | ||
* `Earned Value Management introduction <https://www.humphreys-assoc.com/evms/basic-concepts-earned-value-management-evm-ta-a-74.html>`_ | ||
* `Wikipedia Entry <https://en.wikipedia.org/wiki/Earned_value_management>`_ | ||
|
||
Configuration | ||
============= | ||
|
||
To fully be able to use the report, the following information must be properly maintained: | ||
|
||
* Cost price in the products associated to resources | ||
* Resources lines should contain valid cost and total cost. | ||
* Employees should contain a valid resource product (comparable to the one in the Resource lines) | ||
* The time spent on Timesheets should be properly recorded | ||
|
||
Usage | ||
===== | ||
|
||
#. In the Business requirement, you add Deliverable Lines as necessary,with the | ||
corresponding Resources lines. | ||
#. When the BR is validated the project should be created so that the users can | ||
manage their tasks. | ||
#. When the users spend time on a given task they should input their timesheets | ||
accordingly in the task. | ||
|
||
.. note:: | ||
When creating new tasks, the related BR should be set up properly in the task in | ||
order to be properly accounted | ||
|
||
.. figure:: static/img/bus_req_category.png | ||
:width: 600 px | ||
:alt: Inputing the deliverables and resources lines | ||
|
||
|
||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas | ||
:alt: Try me on Runbot | ||
:target: https://runbot.odoo-community.org/runbot/222/8.0 | ||
|
||
Known issues / Roadmap | ||
====================== | ||
|
||
* Needs timesheets on the tasks related to BR. In the future we might think of a way | ||
to input TS on project directly | ||
|
||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues <https://github.com/OCA/business-requirement/issues>`_. | ||
In case of trouble, please check there if your issue has already been reported. | ||
If you spotted it first, help us smashing it by providing a detailed and welcomed feedback. | ||
|
||
|
||
Credits | ||
======= | ||
|
||
Contributors | ||
------------ | ||
|
||
* Eric Caudal <[email protected]> | ||
|
||
Maintainer | ||
---------- | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
This module is maintained by the OCA. | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
To contribute to this module, please visit https://odoo-community.org. |
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 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (https://www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
from . import report |
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,23 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (https://www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
{ | ||
'name': 'Earned Value Management', | ||
'category': 'Business Requirements Management', | ||
'summary': 'Manage the Earned Value for your customers', | ||
'version': '8.0.1.0.0', | ||
'website': 'https://www.elico-corp.com/', | ||
'author': 'Elico Corp, Odoo Community Association (OCA)', | ||
'depends': [ | ||
'hr_timesheet', | ||
'project_timesheet', | ||
'business_requirement_deliverable_cost', | ||
'business_requirement_deliverable_project', | ||
], | ||
'data': [ | ||
'security/ir.model.access.csv', | ||
'report/br_earned_value_report_view.xml', | ||
], | ||
'license': 'AGPL-3', | ||
'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,5 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
|
||
from . import br_earned_value_report |
243 changes: 243 additions & 0 deletions
243
business_requirement_earned_value/report/br_earned_value_report.py
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,243 @@ | ||
# -*- coding: utf-8 -*- | ||
# © 2017 Elico Corp (https://www.elico-corp.com). | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). | ||
from openerp import tools | ||
from openerp import fields, models | ||
|
||
|
||
class BusinessRequirementEarnedValueReport(models.Model): | ||
_name = "business.requirement.earned.value.report" | ||
_description = "Earned Value Report" | ||
_auto = False | ||
|
||
name = fields.Char('Name', readonly=True) | ||
partner_id = fields.Many2one('res.partner', 'Customer', | ||
readonly=True) | ||
project_id = fields.Many2one('project.project', 'Master Project', | ||
readonly=True) | ||
res_product = fields.Many2one('product.product', 'Res Product', | ||
readonly=True) | ||
hr_timesheet_product = fields.Many2one('product.product', | ||
'HR Timesheet Product', | ||
readonly=True) | ||
planned_time_in_rl = fields.Float('Planned Time', readonly=True) | ||
product_cost_from_rl = fields.Float('Unit Cost', readonly=True) | ||
planned_value = fields.Float('Planned Value', readonly=True) | ||
actual_time_in_timesheet = fields.Float('Actual Time', | ||
readonly=True) | ||
product_cost_from_timesheet_product =\ | ||
fields.Float('Act. Unit Cost', | ||
readonly=True) | ||
actual_cost = fields.Float('Actual Cost', readonly=True) | ||
variance = fields.Float('Variance', readonly=True) | ||
per_variances = fields.Float('% Variance', readonly=True) | ||
remaining_hours = fields.Float('Remaining time', readonly=True) | ||
total_expected_time = fields.Float('Total Exp. time', readonly=True) | ||
project_completion = fields.Float('% Completion', readonly=True) | ||
earned_value = fields.Float('Earned Value', readonly=True) | ||
|
||
def _select(self): | ||
select_str = """ | ||
SELECT | ||
br.id, | ||
CONCAT(br.name,'[',br.description,']') as name, | ||
br.partner_id AS partner_id, | ||
br.project_id AS project_id, | ||
ptm.id AS hr_timesheet_product, | ||
SUM(res.qty) AS planned_time_in_rl, | ||
SUM(res.unit_price) AS product_cost_from_rl, | ||
(SUM(res.qty) * SUM(res.unit_price)) AS planned_value, | ||
(SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) | ||
AS actual_time_in_timesheet, | ||
(ptm.list_price) AS product_cost_from_timesheet_product, | ||
((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) * ptm.list_price) | ||
AS actual_cost, | ||
CASE | ||
WHEN (SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
(((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) * ptm.list_price) - (SUM(res.qty | ||
) * SUM(res.unit_price))) | ||
ElSE 0.0 END AS variance, | ||
CASE | ||
WHEN | ||
(SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
(abs(((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) * ptm.list_price) - (SUM(res.qty | ||
) * SUM(res.unit_price))) / | ||
SUM(res.unit_price)) | ||
ElSE 0.0 END AS per_variances, | ||
CASE | ||
WHEN | ||
(SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
(SELECT | ||
SUM(pt.remaining_hours) | ||
FROM | ||
project_task pt | ||
WHERE pt.business_requirement_id = br.id) | ||
ElSE 0.0 END AS remaining_hours, | ||
CASE | ||
WHEN | ||
(SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) + (SELECT | ||
SUM(pt.remaining_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id)) | ||
ElSE 0.0 END AS total_expected_time, | ||
CASE | ||
WHEN ((SELECT | ||
SUM(pt.remaining_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id)) > 0 | ||
THEN | ||
CASE | ||
WHEN | ||
(SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) / ((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) + (SELECT | ||
SUM(pt.remaining_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) | ||
) * 100) ELSE 0.0 END | ||
ElSE 0.0 END AS project_completion, | ||
CASE | ||
WHEN | ||
(SELECT | ||
SUM(pt.remaining_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
CASE | ||
WHEN | ||
(SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id) > 0 | ||
THEN | ||
((SUM(res.qty) * SUM(res.unit_price) | ||
) * ((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) / ((SELECT | ||
SUM(pt.effective_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id | ||
) + (SELECT | ||
SUM(pt.remaining_hours) | ||
FROM | ||
project_task pt | ||
WHERE | ||
pt.business_requirement_id = br.id)))) | ||
ElSE 0.0 END | ||
ElSE 0.0 END AS earned_value | ||
""" | ||
return select_str | ||
|
||
def _from(self): | ||
from_str = """ | ||
business_requirement br | ||
LEFT JOIN business_requirement_deliverable dlv | ||
ON dlv.business_requirement_id = br.id | ||
LEFT JOIN business_requirement_resource res | ||
ON res.business_requirement_deliverable_id = dlv.id | ||
JOIN product_template as ptm | ||
ON ptm.id = res.product_id | ||
""" | ||
return from_str | ||
|
||
def _group_by(self): | ||
group_by_str = """ | ||
GROUP BY | ||
br.id,ptm.id | ||
""" | ||
return group_by_str | ||
|
||
def init(self, cr): | ||
tools.drop_view_if_exists(cr, self._table) | ||
cr.execute("""CREATE or REPLACE VIEW %s as ( | ||
%s | ||
FROM ( %s ) | ||
%s | ||
)""" % (self._table, self._select(), self._from(), | ||
self._group_by())) |
Oops, something went wrong.